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.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <const char *, size_t> pair.
169 * Most other languages have a string type which can contain
170 * ASCII NUL. We use whatever type is appropriate for each
172 * Buffers are limited by the total message size. To transfer
173 * large blocks of data, use FileIn/FileOut parameters instead.
174 * To return an arbitrary buffer, use RBufferOut.
179 | ProtocolLimitWarning (* display warning about protocol size limits *)
180 | DangerWillRobinson (* flags particularly dangerous commands *)
181 | FishAlias of string (* provide an alias for this cmd in guestfish *)
182 | FishOutput of fish_output_t (* how to display output in guestfish *)
183 | NotInFish (* do not export via guestfish *)
184 | NotInDocs (* do not add this function to documentation *)
185 | DeprecatedBy of string (* function is deprecated, use .. instead *)
186 | Optional of string (* function is part of an optional group *)
189 | FishOutputOctal (* for int return, print in octal *)
190 | FishOutputHexadecimal (* for int return, print in hex *)
192 (* You can supply zero or as many tests as you want per API call.
194 * Note that the test environment has 3 block devices, of size 500MB,
195 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196 * a fourth ISO block device with some known files on it (/dev/sdd).
198 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199 * Number of cylinders was 63 for IDE emulated disks with precisely
200 * the same size. How exactly this is calculated is a mystery.
202 * The ISO block device (/dev/sdd) comes from images/test.iso.
204 * To be able to run the tests in a reasonable amount of time,
205 * the virtual machine and block devices are reused between tests.
206 * So don't try testing kill_subprocess :-x
208 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
210 * Don't assume anything about the previous contents of the block
211 * devices. Use 'Init*' to create some initial scenarios.
213 * You can add a prerequisite clause to any individual test. This
214 * is a run-time check, which, if it fails, causes the test to be
215 * skipped. Useful if testing a command which might not work on
216 * all variations of libguestfs builds. A test that has prerequisite
217 * of 'Always' is run unconditionally.
219 * In addition, packagers can skip individual tests by setting the
220 * environment variables: eg:
221 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
222 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
224 type tests = (test_init * test_prereq * test) list
226 (* Run the command sequence and just expect nothing to fail. *)
229 (* Run the command sequence and expect the output of the final
230 * command to be the string.
232 | TestOutput of seq * string
234 (* Run the command sequence and expect the output of the final
235 * command to be the list of strings.
237 | TestOutputList of seq * string list
239 (* Run the command sequence and expect the output of the final
240 * command to be the list of block devices (could be either
241 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242 * character of each string).
244 | TestOutputListOfDevices of seq * string list
246 (* Run the command sequence and expect the output of the final
247 * command to be the integer.
249 | TestOutputInt of seq * int
251 (* Run the command sequence and expect the output of the final
252 * command to be <op> <int>, eg. ">=", "1".
254 | TestOutputIntOp of seq * string * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a true value (!= 0 or != NULL).
259 | TestOutputTrue of seq
261 (* Run the command sequence and expect the output of the final
262 * command to be a false value (== 0 or == NULL, but not an error).
264 | TestOutputFalse of seq
266 (* Run the command sequence and expect the output of the final
267 * command to be a list of the given length (but don't care about
270 | TestOutputLength of seq * int
272 (* Run the command sequence and expect the output of the final
273 * command to be a buffer (RBufferOut), ie. string + size.
275 | TestOutputBuffer of seq * string
277 (* Run the command sequence and expect the output of the final
278 * command to be a structure.
280 | TestOutputStruct of seq * test_field_compare list
282 (* Run the command sequence and expect the final command (only)
285 | TestLastFail of seq
287 and test_field_compare =
288 | CompareWithInt of string * int
289 | CompareWithIntOp of string * string * int
290 | CompareWithString of string * string
291 | CompareFieldsIntEq of string * string
292 | CompareFieldsStrEq of string * string
294 (* Test prerequisites. *)
296 (* Test always runs. *)
299 (* Test is currently disabled - eg. it fails, or it tests some
300 * unimplemented feature.
304 (* 'string' is some C code (a function body) that should return
305 * true or false. The test will run if the code returns true.
309 (* As for 'If' but the test runs _unless_ the code returns true. *)
312 (* Run the test only if 'string' is available in the daemon. *)
313 | IfAvailable of string
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 uuidgen-compatible UUID (used in tests). However to
365 * avoid having the UUID change every time we rebuild the tests,
366 * generate it as a function of the contents of the
369 * Originally I thought uuidgen was using RFC 4122, but it doesn't
372 * Note that the format must be 01234567-0123-0123-0123-0123456789ab
375 let s = Digest.to_hex (Digest.file "src/generator.ml") in
376 String.sub s 0 8 ^ "-"
377 ^ String.sub s 8 4 ^ "-"
378 ^ String.sub s 12 4 ^ "-"
379 ^ String.sub s 16 4 ^ "-"
382 (* These test functions are used in the language binding tests. *)
384 let test_all_args = [
387 StringList "strlist";
396 let test_all_rets = [
397 (* except for RErr, which is tested thoroughly elsewhere *)
398 "test0rint", RInt "valout";
399 "test0rint64", RInt64 "valout";
400 "test0rbool", RBool "valout";
401 "test0rconststring", RConstString "valout";
402 "test0rconstoptstring", RConstOptString "valout";
403 "test0rstring", RString "valout";
404 "test0rstringlist", RStringList "valout";
405 "test0rstruct", RStruct ("valout", "lvm_pv");
406 "test0rstructlist", RStructList ("valout", "lvm_pv");
407 "test0rhashtable", RHashtable "valout";
410 let test_functions = [
411 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
413 "internal test function - do not use",
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 parameter type correctly.
419 It echos the contents of each parameter to stdout.
421 You probably don't want to call this function.");
425 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
427 "internal test function - do not use",
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
433 It converts string C<val> to the return type.
435 You probably don't want to call this function.");
436 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
438 "internal test function - do not use",
440 This is an internal test function which is used to test whether
441 the automatically generated bindings can handle every possible
442 return type correctly.
444 This function always returns an error.
446 You probably don't want to call this function.")]
450 (* non_daemon_functions are any functions which don't get processed
451 * in the daemon, eg. functions for setting and getting local
452 * configuration values.
455 let non_daemon_functions = test_functions @ [
456 ("launch", (RErr, []), -1, [FishAlias "run"],
458 "launch the qemu subprocess",
460 Internally libguestfs is implemented by running a virtual machine
463 You should call this after configuring the handle
464 (eg. adding drives) but before performing any actions.");
466 ("wait_ready", (RErr, []), -1, [NotInFish],
468 "wait until the qemu subprocess launches (no op)",
470 This function is a no op.
472 In versions of the API E<lt> 1.0.71 you had to call this function
473 just after calling C<guestfs_launch> to wait for the launch
474 to complete. However this is no longer necessary because
475 C<guestfs_launch> now does the waiting.
477 If you see any calls to this function in code then you can just
478 remove them, unless you want to retain compatibility with older
479 versions of the API.");
481 ("kill_subprocess", (RErr, []), -1, [],
483 "kill the qemu subprocess",
485 This kills the qemu subprocess. You should never need to call this.");
487 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
489 "add an image to examine or modify",
491 This function adds a virtual machine disk image C<filename> to the
492 guest. The first time you call this function, the disk appears as IDE
493 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
496 You don't necessarily need to be root when using libguestfs. However
497 you obviously do need sufficient permissions to access the filename
498 for whatever operations you want to perform (ie. read access if you
499 just want to read the image or write access if you want to modify the
502 This is equivalent to the qemu parameter
503 C<-drive file=filename,cache=off,if=...>.
505 C<cache=off> is omitted in cases where it is not supported by
506 the underlying filesystem.
508 C<if=...> is set at compile time by the configuration option
509 C<./configure --with-drive-if=...>. In the rare case where you
510 might need to change this at run time, use C<guestfs_add_drive_with_if>
511 or C<guestfs_add_drive_ro_with_if>.
513 Note that this call checks for the existence of C<filename>. This
514 stops you from specifying other types of drive which are supported
515 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
516 the general C<guestfs_config> call instead.");
518 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
520 "add a CD-ROM disk image to examine",
522 This function adds a virtual CD-ROM disk image to the guest.
524 This is equivalent to the qemu parameter C<-cdrom filename>.
532 This call checks for the existence of C<filename>. This
533 stops you from specifying other types of drive which are supported
534 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
535 the general C<guestfs_config> call instead.
539 If you just want to add an ISO file (often you use this as an
540 efficient way to transfer large files into the guest), then you
541 should probably use C<guestfs_add_drive_ro> instead.
545 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
547 "add a drive in snapshot mode (read-only)",
549 This adds a drive in snapshot mode, making it effectively
552 Note that writes to the device are allowed, and will be seen for
553 the duration of the guestfs handle, but they are written
554 to a temporary file which is discarded as soon as the guestfs
555 handle is closed. We don't currently have any method to enable
556 changes to be committed, although qemu can support this.
558 This is equivalent to the qemu parameter
559 C<-drive file=filename,snapshot=on,if=...>.
561 C<if=...> is set at compile time by the configuration option
562 C<./configure --with-drive-if=...>. In the rare case where you
563 might need to change this at run time, use C<guestfs_add_drive_with_if>
564 or C<guestfs_add_drive_ro_with_if>.
566 Note that this call checks for the existence of C<filename>. This
567 stops you from specifying other types of drive which are supported
568 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
569 the general C<guestfs_config> call instead.");
571 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
573 "add qemu parameters",
575 This can be used to add arbitrary qemu command line parameters
576 of the form C<-param value>. Actually it's not quite arbitrary - we
577 prevent you from setting some parameters which would interfere with
578 parameters that we use.
580 The first character of C<param> string must be a C<-> (dash).
582 C<value> can be NULL.");
584 ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
586 "set the qemu binary",
588 Set the qemu binary that we will use.
590 The default is chosen when the library was compiled by the
593 You can also override this by setting the C<LIBGUESTFS_QEMU>
594 environment variable.
596 Setting C<qemu> to C<NULL> restores the default qemu binary.
598 Note that you should call this function as early as possible
599 after creating the handle. This is because some pre-launch
600 operations depend on testing qemu features (by running C<qemu -help>).
601 If the qemu binary changes, we don't retest features, and
602 so you might see inconsistent results. Using the environment
603 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
604 the qemu binary at the same time as the handle is created.");
606 ("get_qemu", (RConstString "qemu", []), -1, [],
607 [InitNone, Always, TestRun (
609 "get the qemu binary",
611 Return the current qemu binary.
613 This is always non-NULL. If it wasn't set already, then this will
614 return the default qemu binary name.");
616 ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
618 "set the search path",
620 Set the path that libguestfs searches for kernel and initrd.img.
622 The default is C<$libdir/guestfs> unless overridden by setting
623 C<LIBGUESTFS_PATH> environment variable.
625 Setting C<path> to C<NULL> restores the default path.");
627 ("get_path", (RConstString "path", []), -1, [],
628 [InitNone, Always, TestRun (
630 "get the search path",
632 Return the current search path.
634 This is always non-NULL. If it wasn't set already, then this will
635 return the default path.");
637 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
639 "add options to kernel command line",
641 This function is used to add additional options to the
642 guest kernel command line.
644 The default is C<NULL> unless overridden by setting
645 C<LIBGUESTFS_APPEND> environment variable.
647 Setting C<append> to C<NULL> means I<no> additional options
648 are passed (libguestfs always adds a few of its own).");
650 ("get_append", (RConstOptString "append", []), -1, [],
651 (* This cannot be tested with the current framework. The
652 * function can return NULL in normal operations, which the
653 * test framework interprets as an error.
656 "get the additional kernel options",
658 Return the additional kernel options which are added to the
659 guest kernel command line.
661 If C<NULL> then no options are added.");
663 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
667 If C<autosync> is true, this enables autosync. Libguestfs will make a
668 best effort attempt to run C<guestfs_umount_all> followed by
669 C<guestfs_sync> when the handle is closed
670 (also if the program exits without closing handles).
672 This is disabled by default (except in guestfish where it is
673 enabled by default).");
675 ("get_autosync", (RBool "autosync", []), -1, [],
676 [InitNone, Always, TestRun (
677 [["get_autosync"]])],
680 Get the autosync flag.");
682 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
686 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
688 Verbose messages are disabled unless the environment variable
689 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
691 ("get_verbose", (RBool "verbose", []), -1, [],
695 This returns the verbose messages flag.");
697 ("is_ready", (RBool "ready", []), -1, [],
698 [InitNone, Always, TestOutputTrue (
700 "is ready to accept commands",
702 This returns true iff this handle is ready to accept commands
703 (in the C<READY> state).
705 For more information on states, see L<guestfs(3)>.");
707 ("is_config", (RBool "config", []), -1, [],
708 [InitNone, Always, TestOutputFalse (
710 "is in configuration state",
712 This returns true iff this handle is being configured
713 (in the C<CONFIG> state).
715 For more information on states, see L<guestfs(3)>.");
717 ("is_launching", (RBool "launching", []), -1, [],
718 [InitNone, Always, TestOutputFalse (
719 [["is_launching"]])],
720 "is launching subprocess",
722 This returns true iff this handle is launching the subprocess
723 (in the C<LAUNCHING> state).
725 For more information on states, see L<guestfs(3)>.");
727 ("is_busy", (RBool "busy", []), -1, [],
728 [InitNone, Always, TestOutputFalse (
730 "is busy processing a command",
732 This returns true iff this handle is busy processing a command
733 (in the C<BUSY> state).
735 For more information on states, see L<guestfs(3)>.");
737 ("get_state", (RInt "state", []), -1, [],
739 "get the current state",
741 This returns the current state as an opaque integer. This is
742 only useful for printing debug and internal error messages.
744 For more information on states, see L<guestfs(3)>.");
746 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
747 [InitNone, Always, TestOutputInt (
748 [["set_memsize"; "500"];
749 ["get_memsize"]], 500)],
750 "set memory allocated to the qemu subprocess",
752 This sets the memory size in megabytes allocated to the
753 qemu subprocess. This only has any effect if called before
756 You can also change this by setting the environment
757 variable C<LIBGUESTFS_MEMSIZE> before the handle is
760 For more information on the architecture of libguestfs,
761 see L<guestfs(3)>.");
763 ("get_memsize", (RInt "memsize", []), -1, [],
764 [InitNone, Always, TestOutputIntOp (
765 [["get_memsize"]], ">=", 256)],
766 "get memory allocated to the qemu subprocess",
768 This gets the memory size in megabytes allocated to the
771 If C<guestfs_set_memsize> was not called
772 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
773 then this returns the compiled-in default value for memsize.
775 For more information on the architecture of libguestfs,
776 see L<guestfs(3)>.");
778 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
779 [InitNone, Always, TestOutputIntOp (
780 [["get_pid"]], ">=", 1)],
781 "get PID of qemu subprocess",
783 Return the process ID of the qemu subprocess. If there is no
784 qemu subprocess, then this will return an error.
786 This is an internal call used for debugging and testing.");
788 ("version", (RStruct ("version", "version"), []), -1, [],
789 [InitNone, Always, TestOutputStruct (
790 [["version"]], [CompareWithInt ("major", 1)])],
791 "get the library version number",
793 Return the libguestfs version number that the program is linked
796 Note that because of dynamic linking this is not necessarily
797 the version of libguestfs that you compiled against. You can
798 compile the program, and then at runtime dynamically link
799 against a completely different C<libguestfs.so> library.
801 This call was added in version C<1.0.58>. In previous
802 versions of libguestfs there was no way to get the version
803 number. From C code you can use dynamic linker functions
804 to find out if this symbol exists (if it doesn't, then
805 it's an earlier version).
807 The call returns a structure with four elements. The first
808 three (C<major>, C<minor> and C<release>) are numbers and
809 correspond to the usual version triplet. The fourth element
810 (C<extra>) is a string and is normally empty, but may be
811 used for distro-specific information.
813 To construct the original version string:
814 C<$major.$minor.$release$extra>
816 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
818 I<Note:> Don't use this call to test for availability
819 of features. In enterprise distributions we backport
820 features from later versions into earlier versions,
821 making this an unreliable way to test for features.
822 Use C<guestfs_available> instead.");
824 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
825 [InitNone, Always, TestOutputTrue (
826 [["set_selinux"; "true"];
828 "set SELinux enabled or disabled at appliance boot",
830 This sets the selinux flag that is passed to the appliance
831 at boot time. The default is C<selinux=0> (disabled).
833 Note that if SELinux is enabled, it is always in
834 Permissive mode (C<enforcing=0>).
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
839 ("get_selinux", (RBool "selinux", []), -1, [],
841 "get SELinux enabled flag",
843 This returns the current setting of the selinux flag which
844 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
846 For more information on the architecture of libguestfs,
847 see L<guestfs(3)>.");
849 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
850 [InitNone, Always, TestOutputFalse (
851 [["set_trace"; "false"];
853 "enable or disable command traces",
855 If the command trace flag is set to 1, then commands are
856 printed on stdout before they are executed in a format
857 which is very similar to the one used by guestfish. In
858 other words, you can run a program with this enabled, and
859 you will get out a script which you can feed to guestfish
860 to perform the same set of actions.
862 If you want to trace C API calls into libguestfs (and
863 other libraries) then possibly a better way is to use
864 the external ltrace(1) command.
866 Command traces are disabled unless the environment variable
867 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
869 ("get_trace", (RBool "trace", []), -1, [],
871 "get command trace enabled flag",
873 Return the command trace flag.");
875 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
876 [InitNone, Always, TestOutputFalse (
877 [["set_direct"; "false"];
879 "enable or disable direct appliance mode",
881 If the direct appliance mode flag is enabled, then stdin and
882 stdout are passed directly through to the appliance once it
885 One consequence of this is that log messages aren't caught
886 by the library and handled by C<guestfs_set_log_message_callback>,
887 but go straight to stdout.
889 You probably don't want to use this unless you know what you
892 The default is disabled.");
894 ("get_direct", (RBool "direct", []), -1, [],
896 "get direct appliance mode flag",
898 Return the direct appliance mode flag.");
900 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
901 [InitNone, Always, TestOutputTrue (
902 [["set_recovery_proc"; "true"];
903 ["get_recovery_proc"]])],
904 "enable or disable the recovery process",
906 If this is called with the parameter C<false> then
907 C<guestfs_launch> does not create a recovery process. The
908 purpose of the recovery process is to stop runaway qemu
909 processes in the case where the main program aborts abruptly.
911 This only has any effect if called before C<guestfs_launch>,
912 and the default is true.
914 About the only time when you would want to disable this is
915 if the main process will fork itself into the background
916 (\"daemonize\" itself). In this case the recovery process
917 thinks that the main program has disappeared and so kills
918 qemu, which is not very helpful.");
920 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
922 "get recovery process enabled flag",
924 Return the recovery process enabled flag.");
926 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
928 "add a drive specifying the QEMU block emulation to use",
930 This is the same as C<guestfs_add_drive> but it allows you
931 to specify the QEMU interface emulation to use at run time.");
933 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
935 "add a drive read-only specifying the QEMU block emulation to use",
937 This is the same as C<guestfs_add_drive_ro> but it allows you
938 to specify the QEMU interface emulation to use at run time.");
942 (* daemon_functions are any functions which cause some action
943 * to take place in the daemon.
946 let daemon_functions = [
947 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
948 [InitEmpty, Always, TestOutput (
949 [["part_disk"; "/dev/sda"; "mbr"];
950 ["mkfs"; "ext2"; "/dev/sda1"];
951 ["mount"; "/dev/sda1"; "/"];
952 ["write"; "/new"; "new file contents"];
953 ["cat"; "/new"]], "new file contents")],
954 "mount a guest disk at a position in the filesystem",
956 Mount a guest disk at a position in the filesystem. Block devices
957 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
958 the guest. If those block devices contain partitions, they will have
959 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
962 The rules are the same as for L<mount(2)>: A filesystem must
963 first be mounted on C</> before others can be mounted. Other
964 filesystems can only be mounted on directories which already
967 The mounted filesystem is writable, if we have sufficient permissions
968 on the underlying device.
971 When you use this call, the filesystem options C<sync> and C<noatime>
972 are set implicitly. This was originally done because we thought it
973 would improve reliability, but it turns out that I<-o sync> has a
974 very large negative performance impact and negligible effect on
975 reliability. Therefore we recommend that you avoid using
976 C<guestfs_mount> in any code that needs performance, and instead
977 use C<guestfs_mount_options> (use an empty string for the first
978 parameter if you don't want any options).");
980 ("sync", (RErr, []), 2, [],
981 [ InitEmpty, Always, TestRun [["sync"]]],
982 "sync disks, writes are flushed through to the disk image",
984 This syncs the disk, so that any writes are flushed through to the
985 underlying disk image.
987 You should always call this if you have modified a disk image, before
988 closing the handle.");
990 ("touch", (RErr, [Pathname "path"]), 3, [],
991 [InitBasicFS, Always, TestOutputTrue (
993 ["exists"; "/new"]])],
994 "update file timestamps or create a new file",
996 Touch acts like the L<touch(1)> command. It can be used to
997 update the timestamps on a file, or, if the file does not exist,
998 to create a new zero-length file.
1000 This command only works on regular files, and will fail on other
1001 file types such as directories, symbolic links, block special etc.");
1003 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
1004 [InitISOFS, Always, TestOutput (
1005 [["cat"; "/known-2"]], "abcdef\n")],
1006 "list the contents of a file",
1008 Return the contents of the file named C<path>.
1010 Note that this function cannot correctly handle binary files
1011 (specifically, files containing C<\\0> character which is treated
1012 as end of string). For those you need to use the C<guestfs_read_file>
1013 or C<guestfs_download> functions which have a more complex interface.");
1015 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1016 [], (* XXX Tricky to test because it depends on the exact format
1017 * of the 'ls -l' command, which changes between F10 and F11.
1019 "list the files in a directory (long format)",
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd) in the format of 'ls -la'.
1024 This command is mostly useful for interactive sessions. It
1025 is I<not> intended that you try to parse the output string.");
1027 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1028 [InitBasicFS, Always, TestOutputList (
1030 ["touch"; "/newer"];
1031 ["touch"; "/newest"];
1032 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1033 "list the files in a directory",
1035 List the files in C<directory> (relative to the root directory,
1036 there is no cwd). The '.' and '..' entries are not returned, but
1037 hidden files are shown.
1039 This command is mostly useful for interactive sessions. Programs
1040 should probably use C<guestfs_readdir> instead.");
1042 ("list_devices", (RStringList "devices", []), 7, [],
1043 [InitEmpty, Always, TestOutputListOfDevices (
1044 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1045 "list the block devices",
1047 List all the block devices.
1049 The full block device names are returned, eg. C</dev/sda>");
1051 ("list_partitions", (RStringList "partitions", []), 8, [],
1052 [InitBasicFS, Always, TestOutputListOfDevices (
1053 [["list_partitions"]], ["/dev/sda1"]);
1054 InitEmpty, Always, TestOutputListOfDevices (
1055 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1056 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1057 "list the partitions",
1059 List all the partitions detected on all block devices.
1061 The full partition device names are returned, eg. C</dev/sda1>
1063 This does not return logical volumes. For that you will need to
1064 call C<guestfs_lvs>.");
1066 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1067 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1068 [["pvs"]], ["/dev/sda1"]);
1069 InitEmpty, Always, TestOutputListOfDevices (
1070 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071 ["pvcreate"; "/dev/sda1"];
1072 ["pvcreate"; "/dev/sda2"];
1073 ["pvcreate"; "/dev/sda3"];
1074 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1075 "list the LVM physical volumes (PVs)",
1077 List all the physical volumes detected. This is the equivalent
1078 of the L<pvs(8)> command.
1080 This returns a list of just the device names that contain
1081 PVs (eg. C</dev/sda2>).
1083 See also C<guestfs_pvs_full>.");
1085 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1086 [InitBasicFSonLVM, Always, TestOutputList (
1088 InitEmpty, Always, TestOutputList (
1089 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1090 ["pvcreate"; "/dev/sda1"];
1091 ["pvcreate"; "/dev/sda2"];
1092 ["pvcreate"; "/dev/sda3"];
1093 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1094 ["vgcreate"; "VG2"; "/dev/sda3"];
1095 ["vgs"]], ["VG1"; "VG2"])],
1096 "list the LVM volume groups (VGs)",
1098 List all the volumes groups detected. This is the equivalent
1099 of the L<vgs(8)> command.
1101 This returns a list of just the volume group names that were
1102 detected (eg. C<VolGroup00>).
1104 See also C<guestfs_vgs_full>.");
1106 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1107 [InitBasicFSonLVM, Always, TestOutputList (
1108 [["lvs"]], ["/dev/VG/LV"]);
1109 InitEmpty, Always, TestOutputList (
1110 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1111 ["pvcreate"; "/dev/sda1"];
1112 ["pvcreate"; "/dev/sda2"];
1113 ["pvcreate"; "/dev/sda3"];
1114 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1115 ["vgcreate"; "VG2"; "/dev/sda3"];
1116 ["lvcreate"; "LV1"; "VG1"; "50"];
1117 ["lvcreate"; "LV2"; "VG1"; "50"];
1118 ["lvcreate"; "LV3"; "VG2"; "50"];
1119 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1120 "list the LVM logical volumes (LVs)",
1122 List all the logical volumes detected. This is the equivalent
1123 of the L<lvs(8)> command.
1125 This returns a list of the logical volume device names
1126 (eg. C</dev/VolGroup00/LogVol00>).
1128 See also C<guestfs_lvs_full>.");
1130 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1131 [], (* XXX how to test? *)
1132 "list the LVM physical volumes (PVs)",
1134 List all the physical volumes detected. This is the equivalent
1135 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1137 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1138 [], (* XXX how to test? *)
1139 "list the LVM volume groups (VGs)",
1141 List all the volumes groups detected. This is the equivalent
1142 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1144 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1145 [], (* XXX how to test? *)
1146 "list the LVM logical volumes (LVs)",
1148 List all the logical volumes detected. This is the equivalent
1149 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1151 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1152 [InitISOFS, Always, TestOutputList (
1153 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1154 InitISOFS, Always, TestOutputList (
1155 [["read_lines"; "/empty"]], [])],
1156 "read file as lines",
1158 Return the contents of the file named C<path>.
1160 The file contents are returned as a list of lines. Trailing
1161 C<LF> and C<CRLF> character sequences are I<not> returned.
1163 Note that this function cannot correctly handle binary files
1164 (specifically, files containing C<\\0> character which is treated
1165 as end of line). For those you need to use the C<guestfs_read_file>
1166 function which has a more complex interface.");
1168 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1169 [], (* XXX Augeas code needs tests. *)
1170 "create a new Augeas handle",
1172 Create a new Augeas handle for editing configuration files.
1173 If there was any previous Augeas handle associated with this
1174 guestfs session, then it is closed.
1176 You must call this before using any other C<guestfs_aug_*>
1179 C<root> is the filesystem root. C<root> must not be NULL,
1182 The flags are the same as the flags defined in
1183 E<lt>augeas.hE<gt>, the logical I<or> of the following
1188 =item C<AUG_SAVE_BACKUP> = 1
1190 Keep the original file with a C<.augsave> extension.
1192 =item C<AUG_SAVE_NEWFILE> = 2
1194 Save changes into a file with extension C<.augnew>, and
1195 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1197 =item C<AUG_TYPE_CHECK> = 4
1199 Typecheck lenses (can be expensive).
1201 =item C<AUG_NO_STDINC> = 8
1203 Do not use standard load path for modules.
1205 =item C<AUG_SAVE_NOOP> = 16
1207 Make save a no-op, just record what would have been changed.
1209 =item C<AUG_NO_LOAD> = 32
1211 Do not load the tree in C<guestfs_aug_init>.
1215 To close the handle, you can call C<guestfs_aug_close>.
1217 To find out more about Augeas, see L<http://augeas.net/>.");
1219 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1220 [], (* XXX Augeas code needs tests. *)
1221 "close the current Augeas handle",
1223 Close the current Augeas handle and free up any resources
1224 used by it. After calling this, you have to call
1225 C<guestfs_aug_init> again before you can use any other
1226 Augeas functions.");
1228 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1229 [], (* XXX Augeas code needs tests. *)
1230 "define an Augeas variable",
1232 Defines an Augeas variable C<name> whose value is the result
1233 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1236 On success this returns the number of nodes in C<expr>, or
1237 C<0> if C<expr> evaluates to something which is not a nodeset.");
1239 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1240 [], (* XXX Augeas code needs tests. *)
1241 "define an Augeas node",
1243 Defines a variable C<name> whose value is the result of
1246 If C<expr> evaluates to an empty nodeset, a node is created,
1247 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1248 C<name> will be the nodeset containing that single node.
1250 On success this returns a pair containing the
1251 number of nodes in the nodeset, and a boolean flag
1252 if a node was created.");
1254 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1255 [], (* XXX Augeas code needs tests. *)
1256 "look up the value of an Augeas path",
1258 Look up the value associated with C<path>. If C<path>
1259 matches exactly one node, the C<value> is returned.");
1261 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1262 [], (* XXX Augeas code needs tests. *)
1263 "set Augeas path to value",
1265 Set the value associated with C<path> to C<val>.
1267 In the Augeas API, it is possible to clear a node by setting
1268 the value to NULL. Due to an oversight in the libguestfs API
1269 you cannot do that with this call. Instead you must use the
1270 C<guestfs_aug_clear> call.");
1272 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1273 [], (* XXX Augeas code needs tests. *)
1274 "insert a sibling Augeas node",
1276 Create a new sibling C<label> for C<path>, inserting it into
1277 the tree before or after C<path> (depending on the boolean
1280 C<path> must match exactly one existing node in the tree, and
1281 C<label> must be a label, ie. not contain C</>, C<*> or end
1282 with a bracketed index C<[N]>.");
1284 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1285 [], (* XXX Augeas code needs tests. *)
1286 "remove an Augeas path",
1288 Remove C<path> and all of its children.
1290 On success this returns the number of entries which were removed.");
1292 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1293 [], (* XXX Augeas code needs tests. *)
1296 Move the node C<src> to C<dest>. C<src> must match exactly
1297 one node. C<dest> is overwritten if it exists.");
1299 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1300 [], (* XXX Augeas code needs tests. *)
1301 "return Augeas nodes which match augpath",
1303 Returns a list of paths which match the path expression C<path>.
1304 The returned paths are sufficiently qualified so that they match
1305 exactly one node in the current tree.");
1307 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1308 [], (* XXX Augeas code needs tests. *)
1309 "write all pending Augeas changes to disk",
1311 This writes all pending changes to disk.
1313 The flags which were passed to C<guestfs_aug_init> affect exactly
1314 how files are saved.");
1316 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1317 [], (* XXX Augeas code needs tests. *)
1318 "load files into the tree",
1320 Load files into the tree.
1322 See C<aug_load> in the Augeas documentation for the full gory
1325 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1326 [], (* XXX Augeas code needs tests. *)
1327 "list Augeas nodes under augpath",
1329 This is just a shortcut for listing C<guestfs_aug_match>
1330 C<path/*> and sorting the resulting nodes into alphabetical order.");
1332 ("rm", (RErr, [Pathname "path"]), 29, [],
1333 [InitBasicFS, Always, TestRun
1336 InitBasicFS, Always, TestLastFail
1338 InitBasicFS, Always, TestLastFail
1343 Remove the single file C<path>.");
1345 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1346 [InitBasicFS, Always, TestRun
1349 InitBasicFS, Always, TestLastFail
1350 [["rmdir"; "/new"]];
1351 InitBasicFS, Always, TestLastFail
1353 ["rmdir"; "/new"]]],
1354 "remove a directory",
1356 Remove the single directory C<path>.");
1358 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1359 [InitBasicFS, Always, TestOutputFalse
1361 ["mkdir"; "/new/foo"];
1362 ["touch"; "/new/foo/bar"];
1364 ["exists"; "/new"]]],
1365 "remove a file or directory recursively",
1367 Remove the file or directory C<path>, recursively removing the
1368 contents if its a directory. This is like the C<rm -rf> shell
1371 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1372 [InitBasicFS, Always, TestOutputTrue
1374 ["is_dir"; "/new"]];
1375 InitBasicFS, Always, TestLastFail
1376 [["mkdir"; "/new/foo/bar"]]],
1377 "create a directory",
1379 Create a directory named C<path>.");
1381 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1382 [InitBasicFS, Always, TestOutputTrue
1383 [["mkdir_p"; "/new/foo/bar"];
1384 ["is_dir"; "/new/foo/bar"]];
1385 InitBasicFS, Always, TestOutputTrue
1386 [["mkdir_p"; "/new/foo/bar"];
1387 ["is_dir"; "/new/foo"]];
1388 InitBasicFS, Always, TestOutputTrue
1389 [["mkdir_p"; "/new/foo/bar"];
1390 ["is_dir"; "/new"]];
1391 (* Regression tests for RHBZ#503133: *)
1392 InitBasicFS, Always, TestRun
1394 ["mkdir_p"; "/new"]];
1395 InitBasicFS, Always, TestLastFail
1397 ["mkdir_p"; "/new"]]],
1398 "create a directory and parents",
1400 Create a directory named C<path>, creating any parent directories
1401 as necessary. This is like the C<mkdir -p> shell command.");
1403 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1404 [], (* XXX Need stat command to test *)
1407 Change the mode (permissions) of C<path> to C<mode>. Only
1408 numeric modes are supported.
1410 I<Note>: When using this command from guestfish, C<mode>
1411 by default would be decimal, unless you prefix it with
1412 C<0> to get octal, ie. use C<0700> not C<700>.
1414 The mode actually set is affected by the umask.");
1416 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1417 [], (* XXX Need stat command to test *)
1418 "change file owner and group",
1420 Change the file owner to C<owner> and group to C<group>.
1422 Only numeric uid and gid are supported. If you want to use
1423 names, you will need to locate and parse the password file
1424 yourself (Augeas support makes this relatively easy).");
1426 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1427 [InitISOFS, Always, TestOutputTrue (
1428 [["exists"; "/empty"]]);
1429 InitISOFS, Always, TestOutputTrue (
1430 [["exists"; "/directory"]])],
1431 "test if file or directory exists",
1433 This returns C<true> if and only if there is a file, directory
1434 (or anything) with the given C<path> name.
1436 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1438 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1439 [InitISOFS, Always, TestOutputTrue (
1440 [["is_file"; "/known-1"]]);
1441 InitISOFS, Always, TestOutputFalse (
1442 [["is_file"; "/directory"]])],
1443 "test if a regular file",
1445 This returns C<true> if and only if there is a regular file
1446 with the given C<path> name. Note that it returns false for
1447 other objects like directories.
1449 See also C<guestfs_stat>.");
1451 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1452 [InitISOFS, Always, TestOutputFalse (
1453 [["is_dir"; "/known-3"]]);
1454 InitISOFS, Always, TestOutputTrue (
1455 [["is_dir"; "/directory"]])],
1456 "test if a directory",
1458 This returns C<true> if and only if there is a directory
1459 with the given C<path> name. Note that it returns false for
1460 other objects like files.
1462 See also C<guestfs_stat>.");
1464 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1465 [InitEmpty, Always, TestOutputListOfDevices (
1466 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467 ["pvcreate"; "/dev/sda1"];
1468 ["pvcreate"; "/dev/sda2"];
1469 ["pvcreate"; "/dev/sda3"];
1470 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1471 "create an LVM physical volume",
1473 This creates an LVM physical volume on the named C<device>,
1474 where C<device> should usually be a partition name such
1477 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1478 [InitEmpty, Always, TestOutputList (
1479 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1480 ["pvcreate"; "/dev/sda1"];
1481 ["pvcreate"; "/dev/sda2"];
1482 ["pvcreate"; "/dev/sda3"];
1483 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1484 ["vgcreate"; "VG2"; "/dev/sda3"];
1485 ["vgs"]], ["VG1"; "VG2"])],
1486 "create an LVM volume group",
1488 This creates an LVM volume group called C<volgroup>
1489 from the non-empty list of physical volumes C<physvols>.");
1491 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1492 [InitEmpty, Always, TestOutputList (
1493 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1494 ["pvcreate"; "/dev/sda1"];
1495 ["pvcreate"; "/dev/sda2"];
1496 ["pvcreate"; "/dev/sda3"];
1497 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1498 ["vgcreate"; "VG2"; "/dev/sda3"];
1499 ["lvcreate"; "LV1"; "VG1"; "50"];
1500 ["lvcreate"; "LV2"; "VG1"; "50"];
1501 ["lvcreate"; "LV3"; "VG2"; "50"];
1502 ["lvcreate"; "LV4"; "VG2"; "50"];
1503 ["lvcreate"; "LV5"; "VG2"; "50"];
1505 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1506 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1507 "create an LVM logical volume",
1509 This creates an LVM logical volume called C<logvol>
1510 on the volume group C<volgroup>, with C<size> megabytes.");
1512 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1513 [InitEmpty, Always, TestOutput (
1514 [["part_disk"; "/dev/sda"; "mbr"];
1515 ["mkfs"; "ext2"; "/dev/sda1"];
1516 ["mount_options"; ""; "/dev/sda1"; "/"];
1517 ["write"; "/new"; "new file contents"];
1518 ["cat"; "/new"]], "new file contents")],
1519 "make a filesystem",
1521 This creates a filesystem on C<device> (usually a partition
1522 or LVM logical volume). The filesystem type is C<fstype>, for
1525 ("sfdisk", (RErr, [Device "device";
1526 Int "cyls"; Int "heads"; Int "sectors";
1527 StringList "lines"]), 43, [DangerWillRobinson],
1529 "create partitions on a block device",
1531 This is a direct interface to the L<sfdisk(8)> program for creating
1532 partitions on block devices.
1534 C<device> should be a block device, for example C</dev/sda>.
1536 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1537 and sectors on the device, which are passed directly to sfdisk as
1538 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1539 of these, then the corresponding parameter is omitted. Usually for
1540 'large' disks, you can just pass C<0> for these, but for small
1541 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1542 out the right geometry and you will need to tell it.
1544 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1545 information refer to the L<sfdisk(8)> manpage.
1547 To create a single partition occupying the whole disk, you would
1548 pass C<lines> as a single element list, when the single element being
1549 the string C<,> (comma).
1551 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1552 C<guestfs_part_init>");
1554 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1555 (* Regression test for RHBZ#597135. *)
1556 [InitBasicFS, Always, TestLastFail
1557 [["write_file"; "/new"; "abc"; "10000"]]],
1560 This call creates a file called C<path>. The contents of the
1561 file is the string C<content> (which can contain any 8 bit data),
1562 with length C<size>.
1564 As a special case, if C<size> is C<0>
1565 then the length is calculated using C<strlen> (so in this case
1566 the content cannot contain embedded ASCII NULs).
1568 I<NB.> Owing to a bug, writing content containing ASCII NUL
1569 characters does I<not> work, even if the length is specified.");
1571 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1572 [InitEmpty, Always, TestOutputListOfDevices (
1573 [["part_disk"; "/dev/sda"; "mbr"];
1574 ["mkfs"; "ext2"; "/dev/sda1"];
1575 ["mount_options"; ""; "/dev/sda1"; "/"];
1576 ["mounts"]], ["/dev/sda1"]);
1577 InitEmpty, Always, TestOutputList (
1578 [["part_disk"; "/dev/sda"; "mbr"];
1579 ["mkfs"; "ext2"; "/dev/sda1"];
1580 ["mount_options"; ""; "/dev/sda1"; "/"];
1583 "unmount a filesystem",
1585 This unmounts the given filesystem. The filesystem may be
1586 specified either by its mountpoint (path) or the device which
1587 contains the filesystem.");
1589 ("mounts", (RStringList "devices", []), 46, [],
1590 [InitBasicFS, Always, TestOutputListOfDevices (
1591 [["mounts"]], ["/dev/sda1"])],
1592 "show mounted filesystems",
1594 This returns the list of currently mounted filesystems. It returns
1595 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1597 Some internal mounts are not shown.
1599 See also: C<guestfs_mountpoints>");
1601 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1602 [InitBasicFS, Always, TestOutputList (
1605 (* check that umount_all can unmount nested mounts correctly: *)
1606 InitEmpty, Always, TestOutputList (
1607 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1608 ["mkfs"; "ext2"; "/dev/sda1"];
1609 ["mkfs"; "ext2"; "/dev/sda2"];
1610 ["mkfs"; "ext2"; "/dev/sda3"];
1611 ["mount_options"; ""; "/dev/sda1"; "/"];
1613 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1614 ["mkdir"; "/mp1/mp2"];
1615 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1616 ["mkdir"; "/mp1/mp2/mp3"];
1619 "unmount all filesystems",
1621 This unmounts all mounted filesystems.
1623 Some internal mounts are not unmounted by this call.");
1625 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1627 "remove all LVM LVs, VGs and PVs",
1629 This command removes all LVM logical volumes, volume groups
1630 and physical volumes.");
1632 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1633 [InitISOFS, Always, TestOutput (
1634 [["file"; "/empty"]], "empty");
1635 InitISOFS, Always, TestOutput (
1636 [["file"; "/known-1"]], "ASCII text");
1637 InitISOFS, Always, TestLastFail (
1638 [["file"; "/notexists"]]);
1639 InitISOFS, Always, TestOutput (
1640 [["file"; "/abssymlink"]], "symbolic link");
1641 InitISOFS, Always, TestOutput (
1642 [["file"; "/directory"]], "directory")],
1643 "determine file type",
1645 This call uses the standard L<file(1)> command to determine
1646 the type or contents of the file.
1648 This call will also transparently look inside various types
1651 The exact command which runs is C<file -zb path>. Note in
1652 particular that the filename is not prepended to the output
1655 This command can also be used on C</dev/> devices
1656 (and partitions, LV names). You can for example use this
1657 to determine if a device contains a filesystem, although
1658 it's usually better to use C<guestfs_vfs_type>.
1660 If the C<path> does not begin with C</dev/> then
1661 this command only works for the content of regular files.
1662 For other file types (directory, symbolic link etc) it
1663 will just return the string C<directory> etc.");
1665 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1666 [InitBasicFS, Always, TestOutput (
1667 [["upload"; "test-command"; "/test-command"];
1668 ["chmod"; "0o755"; "/test-command"];
1669 ["command"; "/test-command 1"]], "Result1");
1670 InitBasicFS, Always, TestOutput (
1671 [["upload"; "test-command"; "/test-command"];
1672 ["chmod"; "0o755"; "/test-command"];
1673 ["command"; "/test-command 2"]], "Result2\n");
1674 InitBasicFS, Always, TestOutput (
1675 [["upload"; "test-command"; "/test-command"];
1676 ["chmod"; "0o755"; "/test-command"];
1677 ["command"; "/test-command 3"]], "\nResult3");
1678 InitBasicFS, Always, TestOutput (
1679 [["upload"; "test-command"; "/test-command"];
1680 ["chmod"; "0o755"; "/test-command"];
1681 ["command"; "/test-command 4"]], "\nResult4\n");
1682 InitBasicFS, Always, TestOutput (
1683 [["upload"; "test-command"; "/test-command"];
1684 ["chmod"; "0o755"; "/test-command"];
1685 ["command"; "/test-command 5"]], "\nResult5\n\n");
1686 InitBasicFS, Always, TestOutput (
1687 [["upload"; "test-command"; "/test-command"];
1688 ["chmod"; "0o755"; "/test-command"];
1689 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1690 InitBasicFS, Always, TestOutput (
1691 [["upload"; "test-command"; "/test-command"];
1692 ["chmod"; "0o755"; "/test-command"];
1693 ["command"; "/test-command 7"]], "");
1694 InitBasicFS, Always, TestOutput (
1695 [["upload"; "test-command"; "/test-command"];
1696 ["chmod"; "0o755"; "/test-command"];
1697 ["command"; "/test-command 8"]], "\n");
1698 InitBasicFS, Always, TestOutput (
1699 [["upload"; "test-command"; "/test-command"];
1700 ["chmod"; "0o755"; "/test-command"];
1701 ["command"; "/test-command 9"]], "\n\n");
1702 InitBasicFS, Always, TestOutput (
1703 [["upload"; "test-command"; "/test-command"];
1704 ["chmod"; "0o755"; "/test-command"];
1705 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1706 InitBasicFS, Always, TestOutput (
1707 [["upload"; "test-command"; "/test-command"];
1708 ["chmod"; "0o755"; "/test-command"];
1709 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1710 InitBasicFS, Always, TestLastFail (
1711 [["upload"; "test-command"; "/test-command"];
1712 ["chmod"; "0o755"; "/test-command"];
1713 ["command"; "/test-command"]])],
1714 "run a command from the guest filesystem",
1716 This call runs a command from the guest filesystem. The
1717 filesystem must be mounted, and must contain a compatible
1718 operating system (ie. something Linux, with the same
1719 or compatible processor architecture).
1721 The single parameter is an argv-style list of arguments.
1722 The first element is the name of the program to run.
1723 Subsequent elements are parameters. The list must be
1724 non-empty (ie. must contain a program name). Note that
1725 the command runs directly, and is I<not> invoked via
1726 the shell (see C<guestfs_sh>).
1728 The return value is anything printed to I<stdout> by
1731 If the command returns a non-zero exit status, then
1732 this function returns an error message. The error message
1733 string is the content of I<stderr> from the command.
1735 The C<$PATH> environment variable will contain at least
1736 C</usr/bin> and C</bin>. If you require a program from
1737 another location, you should provide the full path in the
1740 Shared libraries and data files required by the program
1741 must be available on filesystems which are mounted in the
1742 correct places. It is the caller's responsibility to ensure
1743 all filesystems that are needed are mounted at the right
1746 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1747 [InitBasicFS, Always, TestOutputList (
1748 [["upload"; "test-command"; "/test-command"];
1749 ["chmod"; "0o755"; "/test-command"];
1750 ["command_lines"; "/test-command 1"]], ["Result1"]);
1751 InitBasicFS, Always, TestOutputList (
1752 [["upload"; "test-command"; "/test-command"];
1753 ["chmod"; "0o755"; "/test-command"];
1754 ["command_lines"; "/test-command 2"]], ["Result2"]);
1755 InitBasicFS, Always, TestOutputList (
1756 [["upload"; "test-command"; "/test-command"];
1757 ["chmod"; "0o755"; "/test-command"];
1758 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1759 InitBasicFS, Always, TestOutputList (
1760 [["upload"; "test-command"; "/test-command"];
1761 ["chmod"; "0o755"; "/test-command"];
1762 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1763 InitBasicFS, Always, TestOutputList (
1764 [["upload"; "test-command"; "/test-command"];
1765 ["chmod"; "0o755"; "/test-command"];
1766 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1767 InitBasicFS, Always, TestOutputList (
1768 [["upload"; "test-command"; "/test-command"];
1769 ["chmod"; "0o755"; "/test-command"];
1770 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1771 InitBasicFS, Always, TestOutputList (
1772 [["upload"; "test-command"; "/test-command"];
1773 ["chmod"; "0o755"; "/test-command"];
1774 ["command_lines"; "/test-command 7"]], []);
1775 InitBasicFS, Always, TestOutputList (
1776 [["upload"; "test-command"; "/test-command"];
1777 ["chmod"; "0o755"; "/test-command"];
1778 ["command_lines"; "/test-command 8"]], [""]);
1779 InitBasicFS, Always, TestOutputList (
1780 [["upload"; "test-command"; "/test-command"];
1781 ["chmod"; "0o755"; "/test-command"];
1782 ["command_lines"; "/test-command 9"]], ["";""]);
1783 InitBasicFS, Always, TestOutputList (
1784 [["upload"; "test-command"; "/test-command"];
1785 ["chmod"; "0o755"; "/test-command"];
1786 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1787 InitBasicFS, Always, TestOutputList (
1788 [["upload"; "test-command"; "/test-command"];
1789 ["chmod"; "0o755"; "/test-command"];
1790 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1791 "run a command, returning lines",
1793 This is the same as C<guestfs_command>, but splits the
1794 result into a list of lines.
1796 See also: C<guestfs_sh_lines>");
1798 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1799 [InitISOFS, Always, TestOutputStruct (
1800 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1801 "get file information",
1803 Returns file information for the given C<path>.
1805 This is the same as the C<stat(2)> system call.");
1807 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1808 [InitISOFS, Always, TestOutputStruct (
1809 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1810 "get file information for a symbolic link",
1812 Returns file information for the given C<path>.
1814 This is the same as C<guestfs_stat> except that if C<path>
1815 is a symbolic link, then the link is stat-ed, not the file it
1818 This is the same as the C<lstat(2)> system call.");
1820 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1821 [InitISOFS, Always, TestOutputStruct (
1822 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1823 "get file system statistics",
1825 Returns file system statistics for any mounted file system.
1826 C<path> should be a file or directory in the mounted file system
1827 (typically it is the mount point itself, but it doesn't need to be).
1829 This is the same as the C<statvfs(2)> system call.");
1831 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1833 "get ext2/ext3/ext4 superblock details",
1835 This returns the contents of the ext2, ext3 or ext4 filesystem
1836 superblock on C<device>.
1838 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1839 manpage for more details. The list of fields returned isn't
1840 clearly defined, and depends on both the version of C<tune2fs>
1841 that libguestfs was built against, and the filesystem itself.");
1843 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1844 [InitEmpty, Always, TestOutputTrue (
1845 [["blockdev_setro"; "/dev/sda"];
1846 ["blockdev_getro"; "/dev/sda"]])],
1847 "set block device to read-only",
1849 Sets the block device named C<device> to read-only.
1851 This uses the L<blockdev(8)> command.");
1853 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1854 [InitEmpty, Always, TestOutputFalse (
1855 [["blockdev_setrw"; "/dev/sda"];
1856 ["blockdev_getro"; "/dev/sda"]])],
1857 "set block device to read-write",
1859 Sets the block device named C<device> to read-write.
1861 This uses the L<blockdev(8)> command.");
1863 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1864 [InitEmpty, Always, TestOutputTrue (
1865 [["blockdev_setro"; "/dev/sda"];
1866 ["blockdev_getro"; "/dev/sda"]])],
1867 "is block device set to read-only",
1869 Returns a boolean indicating if the block device is read-only
1870 (true if read-only, false if not).
1872 This uses the L<blockdev(8)> command.");
1874 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1875 [InitEmpty, Always, TestOutputInt (
1876 [["blockdev_getss"; "/dev/sda"]], 512)],
1877 "get sectorsize of block device",
1879 This returns the size of sectors on a block device.
1880 Usually 512, but can be larger for modern devices.
1882 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1885 This uses the L<blockdev(8)> command.");
1887 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1888 [InitEmpty, Always, TestOutputInt (
1889 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1890 "get blocksize of block device",
1892 This returns the block size of a device.
1894 (Note this is different from both I<size in blocks> and
1895 I<filesystem block size>).
1897 This uses the L<blockdev(8)> command.");
1899 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1901 "set blocksize of block device",
1903 This sets the block size of a device.
1905 (Note this is different from both I<size in blocks> and
1906 I<filesystem block size>).
1908 This uses the L<blockdev(8)> command.");
1910 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1911 [InitEmpty, Always, TestOutputInt (
1912 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1913 "get total size of device in 512-byte sectors",
1915 This returns the size of the device in units of 512-byte sectors
1916 (even if the sectorsize isn't 512 bytes ... weird).
1918 See also C<guestfs_blockdev_getss> for the real sector size of
1919 the device, and C<guestfs_blockdev_getsize64> for the more
1920 useful I<size in bytes>.
1922 This uses the L<blockdev(8)> command.");
1924 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1925 [InitEmpty, Always, TestOutputInt (
1926 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1927 "get total size of device in bytes",
1929 This returns the size of the device in bytes.
1931 See also C<guestfs_blockdev_getsz>.
1933 This uses the L<blockdev(8)> command.");
1935 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1936 [InitEmpty, Always, TestRun
1937 [["blockdev_flushbufs"; "/dev/sda"]]],
1938 "flush device buffers",
1940 This tells the kernel to flush internal buffers associated
1943 This uses the L<blockdev(8)> command.");
1945 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1946 [InitEmpty, Always, TestRun
1947 [["blockdev_rereadpt"; "/dev/sda"]]],
1948 "reread partition table",
1950 Reread the partition table on C<device>.
1952 This uses the L<blockdev(8)> command.");
1954 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1955 [InitBasicFS, Always, TestOutput (
1956 (* Pick a file from cwd which isn't likely to change. *)
1957 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958 ["checksum"; "md5"; "/COPYING.LIB"]],
1959 Digest.to_hex (Digest.file "COPYING.LIB"))],
1960 "upload a file from the local machine",
1962 Upload local file C<filename> to C<remotefilename> on the
1965 C<filename> can also be a named pipe.
1967 See also C<guestfs_download>.");
1969 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1970 [InitBasicFS, Always, TestOutput (
1971 (* Pick a file from cwd which isn't likely to change. *)
1972 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1973 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1974 ["upload"; "testdownload.tmp"; "/upload"];
1975 ["checksum"; "md5"; "/upload"]],
1976 Digest.to_hex (Digest.file "COPYING.LIB"))],
1977 "download a file to the local machine",
1979 Download file C<remotefilename> and save it as C<filename>
1980 on the local machine.
1982 C<filename> can also be a named pipe.
1984 See also C<guestfs_upload>, C<guestfs_cat>.");
1986 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1987 [InitISOFS, Always, TestOutput (
1988 [["checksum"; "crc"; "/known-3"]], "2891671662");
1989 InitISOFS, Always, TestLastFail (
1990 [["checksum"; "crc"; "/notexists"]]);
1991 InitISOFS, Always, TestOutput (
1992 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1993 InitISOFS, Always, TestOutput (
1994 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1995 InitISOFS, Always, TestOutput (
1996 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1997 InitISOFS, Always, TestOutput (
1998 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1999 InitISOFS, Always, TestOutput (
2000 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
2001 InitISOFS, Always, TestOutput (
2002 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
2003 (* Test for RHBZ#579608, absolute symbolic links. *)
2004 InitISOFS, Always, TestOutput (
2005 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2006 "compute MD5, SHAx or CRC checksum of file",
2008 This call computes the MD5, SHAx or CRC checksum of the
2011 The type of checksum to compute is given by the C<csumtype>
2012 parameter which must have one of the following values:
2018 Compute the cyclic redundancy check (CRC) specified by POSIX
2019 for the C<cksum> command.
2023 Compute the MD5 hash (using the C<md5sum> program).
2027 Compute the SHA1 hash (using the C<sha1sum> program).
2031 Compute the SHA224 hash (using the C<sha224sum> program).
2035 Compute the SHA256 hash (using the C<sha256sum> program).
2039 Compute the SHA384 hash (using the C<sha384sum> program).
2043 Compute the SHA512 hash (using the C<sha512sum> program).
2047 The checksum is returned as a printable string.
2049 To get the checksum for a device, use C<guestfs_checksum_device>.
2051 To get the checksums for many files, use C<guestfs_checksums_out>.");
2053 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2054 [InitBasicFS, Always, TestOutput (
2055 [["tar_in"; "../images/helloworld.tar"; "/"];
2056 ["cat"; "/hello"]], "hello\n")],
2057 "unpack tarfile to directory",
2059 This command uploads and unpacks local file C<tarfile> (an
2060 I<uncompressed> tar file) into C<directory>.
2062 To upload a compressed tarball, use C<guestfs_tgz_in>
2063 or C<guestfs_txz_in>.");
2065 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2067 "pack directory into tarfile",
2069 This command packs the contents of C<directory> and downloads
2070 it to local file C<tarfile>.
2072 To download a compressed tarball, use C<guestfs_tgz_out>
2073 or C<guestfs_txz_out>.");
2075 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2076 [InitBasicFS, Always, TestOutput (
2077 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2078 ["cat"; "/hello"]], "hello\n")],
2079 "unpack compressed tarball to directory",
2081 This command uploads and unpacks local file C<tarball> (a
2082 I<gzip compressed> tar file) into C<directory>.
2084 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2086 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2088 "pack directory into compressed tarball",
2090 This command packs the contents of C<directory> and downloads
2091 it to local file C<tarball>.
2093 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2095 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2096 [InitBasicFS, Always, TestLastFail (
2098 ["mount_ro"; "/dev/sda1"; "/"];
2099 ["touch"; "/new"]]);
2100 InitBasicFS, Always, TestOutput (
2101 [["write"; "/new"; "data"];
2103 ["mount_ro"; "/dev/sda1"; "/"];
2104 ["cat"; "/new"]], "data")],
2105 "mount a guest disk, read-only",
2107 This is the same as the C<guestfs_mount> command, but it
2108 mounts the filesystem with the read-only (I<-o ro>) flag.");
2110 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2112 "mount a guest disk with mount options",
2114 This is the same as the C<guestfs_mount> command, but it
2115 allows you to set the mount options as for the
2116 L<mount(8)> I<-o> flag.
2118 If the C<options> parameter is an empty string, then
2119 no options are passed (all options default to whatever
2120 the filesystem uses).");
2122 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2124 "mount a guest disk with mount options and vfstype",
2126 This is the same as the C<guestfs_mount> command, but it
2127 allows you to set both the mount options and the vfstype
2128 as for the L<mount(8)> I<-o> and I<-t> flags.");
2130 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2132 "debugging and internals",
2134 The C<guestfs_debug> command exposes some internals of
2135 C<guestfsd> (the guestfs daemon) that runs inside the
2138 There is no comprehensive help for this command. You have
2139 to look at the file C<daemon/debug.c> in the libguestfs source
2140 to find out what you can do.");
2142 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2143 [InitEmpty, Always, TestOutputList (
2144 [["part_disk"; "/dev/sda"; "mbr"];
2145 ["pvcreate"; "/dev/sda1"];
2146 ["vgcreate"; "VG"; "/dev/sda1"];
2147 ["lvcreate"; "LV1"; "VG"; "50"];
2148 ["lvcreate"; "LV2"; "VG"; "50"];
2149 ["lvremove"; "/dev/VG/LV1"];
2150 ["lvs"]], ["/dev/VG/LV2"]);
2151 InitEmpty, Always, TestOutputList (
2152 [["part_disk"; "/dev/sda"; "mbr"];
2153 ["pvcreate"; "/dev/sda1"];
2154 ["vgcreate"; "VG"; "/dev/sda1"];
2155 ["lvcreate"; "LV1"; "VG"; "50"];
2156 ["lvcreate"; "LV2"; "VG"; "50"];
2157 ["lvremove"; "/dev/VG"];
2159 InitEmpty, Always, TestOutputList (
2160 [["part_disk"; "/dev/sda"; "mbr"];
2161 ["pvcreate"; "/dev/sda1"];
2162 ["vgcreate"; "VG"; "/dev/sda1"];
2163 ["lvcreate"; "LV1"; "VG"; "50"];
2164 ["lvcreate"; "LV2"; "VG"; "50"];
2165 ["lvremove"; "/dev/VG"];
2167 "remove an LVM logical volume",
2169 Remove an LVM logical volume C<device>, where C<device> is
2170 the path to the LV, such as C</dev/VG/LV>.
2172 You can also remove all LVs in a volume group by specifying
2173 the VG name, C</dev/VG>.");
2175 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2176 [InitEmpty, Always, TestOutputList (
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"];
2184 InitEmpty, Always, TestOutputList (
2185 [["part_disk"; "/dev/sda"; "mbr"];
2186 ["pvcreate"; "/dev/sda1"];
2187 ["vgcreate"; "VG"; "/dev/sda1"];
2188 ["lvcreate"; "LV1"; "VG"; "50"];
2189 ["lvcreate"; "LV2"; "VG"; "50"];
2192 "remove an LVM volume group",
2194 Remove an LVM volume group C<vgname>, (for example C<VG>).
2196 This also forcibly removes all logical volumes in the volume
2199 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2200 [InitEmpty, Always, TestOutputListOfDevices (
2201 [["part_disk"; "/dev/sda"; "mbr"];
2202 ["pvcreate"; "/dev/sda1"];
2203 ["vgcreate"; "VG"; "/dev/sda1"];
2204 ["lvcreate"; "LV1"; "VG"; "50"];
2205 ["lvcreate"; "LV2"; "VG"; "50"];
2207 ["pvremove"; "/dev/sda1"];
2209 InitEmpty, Always, TestOutputListOfDevices (
2210 [["part_disk"; "/dev/sda"; "mbr"];
2211 ["pvcreate"; "/dev/sda1"];
2212 ["vgcreate"; "VG"; "/dev/sda1"];
2213 ["lvcreate"; "LV1"; "VG"; "50"];
2214 ["lvcreate"; "LV2"; "VG"; "50"];
2216 ["pvremove"; "/dev/sda1"];
2218 InitEmpty, Always, TestOutputListOfDevices (
2219 [["part_disk"; "/dev/sda"; "mbr"];
2220 ["pvcreate"; "/dev/sda1"];
2221 ["vgcreate"; "VG"; "/dev/sda1"];
2222 ["lvcreate"; "LV1"; "VG"; "50"];
2223 ["lvcreate"; "LV2"; "VG"; "50"];
2225 ["pvremove"; "/dev/sda1"];
2227 "remove an LVM physical volume",
2229 This wipes a physical volume C<device> so that LVM will no longer
2232 The implementation uses the C<pvremove> command which refuses to
2233 wipe physical volumes that contain any volume groups, so you have
2234 to remove those first.");
2236 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2237 [InitBasicFS, Always, TestOutput (
2238 [["set_e2label"; "/dev/sda1"; "testlabel"];
2239 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2240 "set the ext2/3/4 filesystem label",
2242 This sets the ext2/3/4 filesystem label of the filesystem on
2243 C<device> to C<label>. Filesystem labels are limited to
2246 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2247 to return the existing label on a filesystem.");
2249 ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2251 "get the ext2/3/4 filesystem label",
2253 This returns the ext2/3/4 filesystem label of the filesystem on
2256 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2257 (let uuid = uuidgen () in
2258 [InitBasicFS, Always, TestOutput (
2259 [["set_e2uuid"; "/dev/sda1"; uuid];
2260 ["get_e2uuid"; "/dev/sda1"]], uuid);
2261 InitBasicFS, Always, TestOutput (
2262 [["set_e2uuid"; "/dev/sda1"; "clear"];
2263 ["get_e2uuid"; "/dev/sda1"]], "");
2264 (* We can't predict what UUIDs will be, so just check the commands run. *)
2265 InitBasicFS, Always, TestRun (
2266 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2267 InitBasicFS, Always, TestRun (
2268 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2269 "set the ext2/3/4 filesystem UUID",
2271 This sets the ext2/3/4 filesystem UUID of the filesystem on
2272 C<device> to C<uuid>. The format of the UUID and alternatives
2273 such as C<clear>, C<random> and C<time> are described in the
2274 L<tune2fs(8)> manpage.
2276 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2277 to return the existing UUID of a filesystem.");
2279 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2280 (* Regression test for RHBZ#597112. *)
2281 (let uuid = uuidgen () in
2282 [InitBasicFS, Always, TestOutput (
2283 [["mke2journal"; "1024"; "/dev/sdb"];
2284 ["set_e2uuid"; "/dev/sdb"; uuid];
2285 ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2286 "get the ext2/3/4 filesystem UUID",
2288 This returns the ext2/3/4 filesystem UUID of the filesystem on
2291 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2292 [InitBasicFS, Always, TestOutputInt (
2293 [["umount"; "/dev/sda1"];
2294 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2295 InitBasicFS, Always, TestOutputInt (
2296 [["umount"; "/dev/sda1"];
2297 ["zero"; "/dev/sda1"];
2298 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2299 "run the filesystem checker",
2301 This runs the filesystem checker (fsck) on C<device> which
2302 should have filesystem type C<fstype>.
2304 The returned integer is the status. See L<fsck(8)> for the
2305 list of status codes from C<fsck>.
2313 Multiple status codes can be summed together.
2317 A non-zero return code can mean \"success\", for example if
2318 errors have been corrected on the filesystem.
2322 Checking or repairing NTFS volumes is not supported
2327 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2329 ("zero", (RErr, [Device "device"]), 85, [],
2330 [InitBasicFS, Always, TestOutput (
2331 [["umount"; "/dev/sda1"];
2332 ["zero"; "/dev/sda1"];
2333 ["file"; "/dev/sda1"]], "data")],
2334 "write zeroes to the device",
2336 This command writes zeroes over the first few blocks of C<device>.
2338 How many blocks are zeroed isn't specified (but it's I<not> enough
2339 to securely wipe the device). It should be sufficient to remove
2340 any partition tables, filesystem superblocks and so on.
2342 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2344 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2346 * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2347 * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2349 [InitBasicFS, Always, TestOutputTrue (
2350 [["mkdir_p"; "/boot/grub"];
2351 ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2352 ["grub_install"; "/"; "/dev/vda"];
2353 ["is_dir"; "/boot"]])],
2356 This command installs GRUB (the Grand Unified Bootloader) on
2357 C<device>, with the root directory being C<root>.
2359 Note: If grub-install reports the error
2360 \"No suitable drive was found in the generated device map.\"
2361 it may be that you need to create a C</boot/grub/device.map>
2362 file first that contains the mapping between grub device names
2363 and Linux device names. It is usually sufficient to create
2368 replacing C</dev/vda> with the name of the installation device.");
2370 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2371 [InitBasicFS, Always, TestOutput (
2372 [["write"; "/old"; "file content"];
2373 ["cp"; "/old"; "/new"];
2374 ["cat"; "/new"]], "file content");
2375 InitBasicFS, Always, TestOutputTrue (
2376 [["write"; "/old"; "file content"];
2377 ["cp"; "/old"; "/new"];
2378 ["is_file"; "/old"]]);
2379 InitBasicFS, Always, TestOutput (
2380 [["write"; "/old"; "file content"];
2382 ["cp"; "/old"; "/dir/new"];
2383 ["cat"; "/dir/new"]], "file content")],
2386 This copies a file from C<src> to C<dest> where C<dest> is
2387 either a destination filename or destination directory.");
2389 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2390 [InitBasicFS, Always, TestOutput (
2391 [["mkdir"; "/olddir"];
2392 ["mkdir"; "/newdir"];
2393 ["write"; "/olddir/file"; "file content"];
2394 ["cp_a"; "/olddir"; "/newdir"];
2395 ["cat"; "/newdir/olddir/file"]], "file content")],
2396 "copy a file or directory recursively",
2398 This copies a file or directory from C<src> to C<dest>
2399 recursively using the C<cp -a> command.");
2401 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2402 [InitBasicFS, Always, TestOutput (
2403 [["write"; "/old"; "file content"];
2404 ["mv"; "/old"; "/new"];
2405 ["cat"; "/new"]], "file content");
2406 InitBasicFS, Always, TestOutputFalse (
2407 [["write"; "/old"; "file content"];
2408 ["mv"; "/old"; "/new"];
2409 ["is_file"; "/old"]])],
2412 This moves a file from C<src> to C<dest> where C<dest> is
2413 either a destination filename or destination directory.");
2415 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2416 [InitEmpty, Always, TestRun (
2417 [["drop_caches"; "3"]])],
2418 "drop kernel page cache, dentries and inodes",
2420 This instructs the guest kernel to drop its page cache,
2421 and/or dentries and inode caches. The parameter C<whattodrop>
2422 tells the kernel what precisely to drop, see
2423 L<http://linux-mm.org/Drop_Caches>
2425 Setting C<whattodrop> to 3 should drop everything.
2427 This automatically calls L<sync(2)> before the operation,
2428 so that the maximum guest memory is freed.");
2430 ("dmesg", (RString "kmsgs", []), 91, [],
2431 [InitEmpty, Always, TestRun (
2433 "return kernel messages",
2435 This returns the kernel messages (C<dmesg> output) from
2436 the guest kernel. This is sometimes useful for extended
2437 debugging of problems.
2439 Another way to get the same information is to enable
2440 verbose messages with C<guestfs_set_verbose> or by setting
2441 the environment variable C<LIBGUESTFS_DEBUG=1> before
2442 running the program.");
2444 ("ping_daemon", (RErr, []), 92, [],
2445 [InitEmpty, Always, TestRun (
2446 [["ping_daemon"]])],
2447 "ping the guest daemon",
2449 This is a test probe into the guestfs daemon running inside
2450 the qemu subprocess. Calling this function checks that the
2451 daemon responds to the ping message, without affecting the daemon
2452 or attached block device(s) in any other way.");
2454 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2455 [InitBasicFS, Always, TestOutputTrue (
2456 [["write"; "/file1"; "contents of a file"];
2457 ["cp"; "/file1"; "/file2"];
2458 ["equal"; "/file1"; "/file2"]]);
2459 InitBasicFS, Always, TestOutputFalse (
2460 [["write"; "/file1"; "contents of a file"];
2461 ["write"; "/file2"; "contents of another file"];
2462 ["equal"; "/file1"; "/file2"]]);
2463 InitBasicFS, Always, TestLastFail (
2464 [["equal"; "/file1"; "/file2"]])],
2465 "test if two files have equal contents",
2467 This compares the two files C<file1> and C<file2> and returns
2468 true if their content is exactly equal, or false otherwise.
2470 The external L<cmp(1)> program is used for the comparison.");
2472 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2473 [InitISOFS, Always, TestOutputList (
2474 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2475 InitISOFS, Always, TestOutputList (
2476 [["strings"; "/empty"]], []);
2477 (* Test for RHBZ#579608, absolute symbolic links. *)
2478 InitISOFS, Always, TestRun (
2479 [["strings"; "/abssymlink"]])],
2480 "print the printable strings in a file",
2482 This runs the L<strings(1)> command on a file and returns
2483 the list of printable strings found.");
2485 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2486 [InitISOFS, Always, TestOutputList (
2487 [["strings_e"; "b"; "/known-5"]], []);
2488 InitBasicFS, Always, TestOutputList (
2489 [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2490 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2491 "print the printable strings in a file",
2493 This is like the C<guestfs_strings> command, but allows you to
2494 specify the encoding of strings that are looked for in
2495 the source file C<path>.
2497 Allowed encodings are:
2503 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2504 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2508 Single 8-bit-byte characters.
2512 16-bit big endian strings such as those encoded in
2513 UTF-16BE or UCS-2BE.
2515 =item l (lower case letter L)
2517 16-bit little endian such as UTF-16LE and UCS-2LE.
2518 This is useful for examining binaries in Windows guests.
2522 32-bit big endian such as UCS-4BE.
2526 32-bit little endian such as UCS-4LE.
2530 The returned strings are transcoded to UTF-8.");
2532 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2533 [InitISOFS, Always, TestOutput (
2534 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2535 (* Test for RHBZ#501888c2 regression which caused large hexdump
2536 * commands to segfault.
2538 InitISOFS, Always, TestRun (
2539 [["hexdump"; "/100krandom"]]);
2540 (* Test for RHBZ#579608, absolute symbolic links. *)
2541 InitISOFS, Always, TestRun (
2542 [["hexdump"; "/abssymlink"]])],
2543 "dump a file in hexadecimal",
2545 This runs C<hexdump -C> on the given C<path>. The result is
2546 the human-readable, canonical hex dump of the file.");
2548 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2549 [InitNone, Always, TestOutput (
2550 [["part_disk"; "/dev/sda"; "mbr"];
2551 ["mkfs"; "ext3"; "/dev/sda1"];
2552 ["mount_options"; ""; "/dev/sda1"; "/"];
2553 ["write"; "/new"; "test file"];
2554 ["umount"; "/dev/sda1"];
2555 ["zerofree"; "/dev/sda1"];
2556 ["mount_options"; ""; "/dev/sda1"; "/"];
2557 ["cat"; "/new"]], "test file")],
2558 "zero unused inodes and disk blocks on ext2/3 filesystem",
2560 This runs the I<zerofree> program on C<device>. This program
2561 claims to zero unused inodes and disk blocks on an ext2/3
2562 filesystem, thus making it possible to compress the filesystem
2565 You should B<not> run this program if the filesystem is
2568 It is possible that using this program can damage the filesystem
2569 or data on the filesystem.");
2571 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2573 "resize an LVM physical volume",
2575 This resizes (expands or shrinks) an existing LVM physical
2576 volume to match the new size of the underlying device.");
2578 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2579 Int "cyls"; Int "heads"; Int "sectors";
2580 String "line"]), 99, [DangerWillRobinson],
2582 "modify a single partition on a block device",
2584 This runs L<sfdisk(8)> option to modify just the single
2585 partition C<n> (note: C<n> counts from 1).
2587 For other parameters, see C<guestfs_sfdisk>. You should usually
2588 pass C<0> for the cyls/heads/sectors parameters.
2590 See also: C<guestfs_part_add>");
2592 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2594 "display the partition table",
2596 This displays the partition table on C<device>, in the
2597 human-readable output of the L<sfdisk(8)> command. It is
2598 not intended to be parsed.
2600 See also: C<guestfs_part_list>");
2602 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2604 "display the kernel geometry",
2606 This displays the kernel's idea of the geometry of C<device>.
2608 The result is in human-readable format, and not designed to
2611 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2613 "display the disk geometry from the partition table",
2615 This displays the disk geometry of C<device> read from the
2616 partition table. Especially in the case where the underlying
2617 block device has been resized, this can be different from the
2618 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2620 The result is in human-readable format, and not designed to
2623 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2625 "activate or deactivate all volume groups",
2627 This command activates or (if C<activate> is false) deactivates
2628 all logical volumes in all volume groups.
2629 If activated, then they are made known to the
2630 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2631 then those devices disappear.
2633 This command is the same as running C<vgchange -a y|n>");
2635 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2637 "activate or deactivate some volume groups",
2639 This command activates or (if C<activate> is false) deactivates
2640 all logical volumes in the listed volume groups C<volgroups>.
2641 If activated, then they are made known to the
2642 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2643 then those devices disappear.
2645 This command is the same as running C<vgchange -a y|n volgroups...>
2647 Note that if C<volgroups> is an empty list then B<all> volume groups
2648 are activated or deactivated.");
2650 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2651 [InitNone, Always, TestOutput (
2652 [["part_disk"; "/dev/sda"; "mbr"];
2653 ["pvcreate"; "/dev/sda1"];
2654 ["vgcreate"; "VG"; "/dev/sda1"];
2655 ["lvcreate"; "LV"; "VG"; "10"];
2656 ["mkfs"; "ext2"; "/dev/VG/LV"];
2657 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2658 ["write"; "/new"; "test content"];
2660 ["lvresize"; "/dev/VG/LV"; "20"];
2661 ["e2fsck_f"; "/dev/VG/LV"];
2662 ["resize2fs"; "/dev/VG/LV"];
2663 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2664 ["cat"; "/new"]], "test content");
2665 InitNone, Always, TestRun (
2666 (* Make an LV smaller to test RHBZ#587484. *)
2667 [["part_disk"; "/dev/sda"; "mbr"];
2668 ["pvcreate"; "/dev/sda1"];
2669 ["vgcreate"; "VG"; "/dev/sda1"];
2670 ["lvcreate"; "LV"; "VG"; "20"];
2671 ["lvresize"; "/dev/VG/LV"; "10"]])],
2672 "resize an LVM logical volume",
2674 This resizes (expands or shrinks) an existing LVM logical
2675 volume to C<mbytes>. When reducing, data in the reduced part
2678 ("resize2fs", (RErr, [Device "device"]), 106, [],
2679 [], (* lvresize tests this *)
2680 "resize an ext2, ext3 or ext4 filesystem",
2682 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2683 the underlying device.
2685 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2686 on the C<device> before calling this command. For unknown reasons
2687 C<resize2fs> sometimes gives an error about this and sometimes not.
2688 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2689 calling this function.");
2691 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2692 [InitBasicFS, Always, TestOutputList (
2693 [["find"; "/"]], ["lost+found"]);
2694 InitBasicFS, Always, TestOutputList (
2698 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2699 InitBasicFS, Always, TestOutputList (
2700 [["mkdir_p"; "/a/b/c"];
2701 ["touch"; "/a/b/c/d"];
2702 ["find"; "/a/b/"]], ["c"; "c/d"])],
2703 "find all files and directories",
2705 This command lists out all files and directories, recursively,
2706 starting at C<directory>. It is essentially equivalent to
2707 running the shell command C<find directory -print> but some
2708 post-processing happens on the output, described below.
2710 This returns a list of strings I<without any prefix>. Thus
2711 if the directory structure was:
2717 then the returned list from C<guestfs_find> C</tmp> would be
2725 If C<directory> is not a directory, then this command returns
2728 The returned list is sorted.
2730 See also C<guestfs_find0>.");
2732 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2733 [], (* lvresize tests this *)
2734 "check an ext2/ext3 filesystem",
2736 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2737 filesystem checker on C<device>, noninteractively (C<-p>),
2738 even if the filesystem appears to be clean (C<-f>).
2740 This command is only needed because of C<guestfs_resize2fs>
2741 (q.v.). Normally you should use C<guestfs_fsck>.");
2743 ("sleep", (RErr, [Int "secs"]), 109, [],
2744 [InitNone, Always, TestRun (
2746 "sleep for some seconds",
2748 Sleep for C<secs> seconds.");
2750 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2751 [InitNone, Always, TestOutputInt (
2752 [["part_disk"; "/dev/sda"; "mbr"];
2753 ["mkfs"; "ntfs"; "/dev/sda1"];
2754 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2755 InitNone, Always, TestOutputInt (
2756 [["part_disk"; "/dev/sda"; "mbr"];
2757 ["mkfs"; "ext2"; "/dev/sda1"];
2758 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2759 "probe NTFS volume",
2761 This command runs the L<ntfs-3g.probe(8)> command which probes
2762 an NTFS C<device> for mountability. (Not all NTFS volumes can
2763 be mounted read-write, and some cannot be mounted at all).
2765 C<rw> is a boolean flag. Set it to true if you want to test
2766 if the volume can be mounted read-write. Set it to false if
2767 you want to test if the volume can be mounted read-only.
2769 The return value is an integer which C<0> if the operation
2770 would succeed, or some non-zero value documented in the
2771 L<ntfs-3g.probe(8)> manual page.");
2773 ("sh", (RString "output", [String "command"]), 111, [],
2774 [], (* XXX needs tests *)
2775 "run a command via the shell",
2777 This call runs a command from the guest filesystem via the
2780 This is like C<guestfs_command>, but passes the command to:
2782 /bin/sh -c \"command\"
2784 Depending on the guest's shell, this usually results in
2785 wildcards being expanded, shell expressions being interpolated
2788 All the provisos about C<guestfs_command> apply to this call.");
2790 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2791 [], (* XXX needs tests *)
2792 "run a command via the shell returning lines",
2794 This is the same as C<guestfs_sh>, but splits the result
2795 into a list of lines.
2797 See also: C<guestfs_command_lines>");
2799 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2800 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2801 * code in stubs.c, since all valid glob patterns must start with "/".
2802 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2804 [InitBasicFS, Always, TestOutputList (
2805 [["mkdir_p"; "/a/b/c"];
2806 ["touch"; "/a/b/c/d"];
2807 ["touch"; "/a/b/c/e"];
2808 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809 InitBasicFS, Always, TestOutputList (
2810 [["mkdir_p"; "/a/b/c"];
2811 ["touch"; "/a/b/c/d"];
2812 ["touch"; "/a/b/c/e"];
2813 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2814 InitBasicFS, Always, TestOutputList (
2815 [["mkdir_p"; "/a/b/c"];
2816 ["touch"; "/a/b/c/d"];
2817 ["touch"; "/a/b/c/e"];
2818 ["glob_expand"; "/a/*/x/*"]], [])],
2819 "expand a wildcard path",
2821 This command searches for all the pathnames matching
2822 C<pattern> according to the wildcard expansion rules
2825 If no paths match, then this returns an empty list
2826 (note: not an error).
2828 It is just a wrapper around the C L<glob(3)> function
2829 with flags C<GLOB_MARK|GLOB_BRACE>.
2830 See that manual page for more details.");
2832 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2833 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2834 [["scrub_device"; "/dev/sdc"]])],
2835 "scrub (securely wipe) a device",
2837 This command writes patterns over C<device> to make data retrieval
2840 It is an interface to the L<scrub(1)> program. See that
2841 manual page for more details.");
2843 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2844 [InitBasicFS, Always, TestRun (
2845 [["write"; "/file"; "content"];
2846 ["scrub_file"; "/file"]])],
2847 "scrub (securely wipe) a file",
2849 This command writes patterns over a file to make data retrieval
2852 The file is I<removed> after scrubbing.
2854 It is an interface to the L<scrub(1)> program. See that
2855 manual page for more details.");
2857 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2858 [], (* XXX needs testing *)
2859 "scrub (securely wipe) free space",
2861 This command creates the directory C<dir> and then fills it
2862 with files until the filesystem is full, and scrubs the files
2863 as for C<guestfs_scrub_file>, and deletes them.
2864 The intention is to scrub any free space on the partition
2867 It is an interface to the L<scrub(1)> program. See that
2868 manual page for more details.");
2870 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2871 [InitBasicFS, Always, TestRun (
2873 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2874 "create a temporary directory",
2876 This command creates a temporary directory. The
2877 C<template> parameter should be a full pathname for the
2878 temporary directory name with the final six characters being
2881 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2882 the second one being suitable for Windows filesystems.
2884 The name of the temporary directory that was created
2887 The temporary directory is created with mode 0700
2888 and is owned by root.
2890 The caller is responsible for deleting the temporary
2891 directory and its contents after use.
2893 See also: L<mkdtemp(3)>");
2895 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2896 [InitISOFS, Always, TestOutputInt (
2897 [["wc_l"; "/10klines"]], 10000);
2898 (* Test for RHBZ#579608, absolute symbolic links. *)
2899 InitISOFS, Always, TestOutputInt (
2900 [["wc_l"; "/abssymlink"]], 10000)],
2901 "count lines in a file",
2903 This command counts the lines in a file, using the
2904 C<wc -l> external command.");
2906 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2907 [InitISOFS, Always, TestOutputInt (
2908 [["wc_w"; "/10klines"]], 10000)],
2909 "count words in a file",
2911 This command counts the words in a file, using the
2912 C<wc -w> external command.");
2914 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2915 [InitISOFS, Always, TestOutputInt (
2916 [["wc_c"; "/100kallspaces"]], 102400)],
2917 "count characters in a file",
2919 This command counts the characters in a file, using the
2920 C<wc -c> external command.");
2922 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2923 [InitISOFS, Always, TestOutputList (
2924 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2925 (* Test for RHBZ#579608, absolute symbolic links. *)
2926 InitISOFS, Always, TestOutputList (
2927 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2928 "return first 10 lines of a file",
2930 This command returns up to the first 10 lines of a file as
2931 a list of strings.");
2933 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2934 [InitISOFS, Always, TestOutputList (
2935 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2936 InitISOFS, Always, TestOutputList (
2937 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2938 InitISOFS, Always, TestOutputList (
2939 [["head_n"; "0"; "/10klines"]], [])],
2940 "return first N lines of a file",
2942 If the parameter C<nrlines> is a positive number, this returns the first
2943 C<nrlines> lines of the file C<path>.
2945 If the parameter C<nrlines> is a negative number, this returns lines
2946 from the file C<path>, excluding the last C<nrlines> lines.
2948 If the parameter C<nrlines> is zero, this returns an empty list.");
2950 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2951 [InitISOFS, Always, TestOutputList (
2952 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2953 "return last 10 lines of a file",
2955 This command returns up to the last 10 lines of a file as
2956 a list of strings.");
2958 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2959 [InitISOFS, Always, TestOutputList (
2960 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2961 InitISOFS, Always, TestOutputList (
2962 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2963 InitISOFS, Always, TestOutputList (
2964 [["tail_n"; "0"; "/10klines"]], [])],
2965 "return last N lines of a file",
2967 If the parameter C<nrlines> is a positive number, this returns the last
2968 C<nrlines> lines of the file C<path>.
2970 If the parameter C<nrlines> is a negative number, this returns lines
2971 from the file C<path>, starting with the C<-nrlines>th line.
2973 If the parameter C<nrlines> is zero, this returns an empty list.");
2975 ("df", (RString "output", []), 125, [],
2976 [], (* XXX Tricky to test because it depends on the exact format
2977 * of the 'df' command and other imponderables.
2979 "report file system disk space usage",
2981 This command runs the C<df> command to report disk space used.
2983 This command is mostly useful for interactive sessions. It
2984 is I<not> intended that you try to parse the output string.
2985 Use C<statvfs> from programs.");
2987 ("df_h", (RString "output", []), 126, [],
2988 [], (* XXX Tricky to test because it depends on the exact format
2989 * of the 'df' command and other imponderables.
2991 "report file system disk space usage (human readable)",
2993 This command runs the C<df -h> command to report disk space used
2994 in human-readable format.
2996 This command is mostly useful for interactive sessions. It
2997 is I<not> intended that you try to parse the output string.
2998 Use C<statvfs> from programs.");
3000 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
3001 [InitISOFS, Always, TestOutputInt (
3002 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
3003 "estimate file space usage",
3005 This command runs the C<du -s> command to estimate file space
3008 C<path> can be a file or a directory. If C<path> is a directory
3009 then the estimate includes the contents of the directory and all
3010 subdirectories (recursively).
3012 The result is the estimated size in I<kilobytes>
3013 (ie. units of 1024 bytes).");
3015 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3016 [InitISOFS, Always, TestOutputList (
3017 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3018 "list files in an initrd",
3020 This command lists out files contained in an initrd.
3022 The files are listed without any initial C</> character. The
3023 files are listed in the order they appear (not necessarily
3024 alphabetical). Directory names are listed as separate items.
3026 Old Linux kernels (2.4 and earlier) used a compressed ext2
3027 filesystem as initrd. We I<only> support the newer initramfs
3028 format (compressed cpio files).");
3030 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3032 "mount a file using the loop device",
3034 This command lets you mount C<file> (a filesystem image
3035 in a file) on a mount point. It is entirely equivalent to
3036 the command C<mount -o loop file mountpoint>.");
3038 ("mkswap", (RErr, [Device "device"]), 130, [],
3039 [InitEmpty, Always, TestRun (
3040 [["part_disk"; "/dev/sda"; "mbr"];
3041 ["mkswap"; "/dev/sda1"]])],
3042 "create a swap partition",
3044 Create a swap partition on C<device>.");
3046 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3047 [InitEmpty, Always, TestRun (
3048 [["part_disk"; "/dev/sda"; "mbr"];
3049 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3050 "create a swap partition with a label",
3052 Create a swap partition on C<device> with label C<label>.
3054 Note that you cannot attach a swap label to a block device
3055 (eg. C</dev/sda>), just to a partition. This appears to be
3056 a limitation of the kernel or swap tools.");
3058 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3059 (let uuid = uuidgen () in
3060 [InitEmpty, Always, TestRun (
3061 [["part_disk"; "/dev/sda"; "mbr"];
3062 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3063 "create a swap partition with an explicit UUID",
3065 Create a swap partition on C<device> with UUID C<uuid>.");
3067 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3068 [InitBasicFS, Always, TestOutputStruct (
3069 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3070 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3071 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3072 InitBasicFS, Always, TestOutputStruct (
3073 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3074 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3075 "make block, character or FIFO devices",
3077 This call creates block or character special devices, or
3078 named pipes (FIFOs).
3080 The C<mode> parameter should be the mode, using the standard
3081 constants. C<devmajor> and C<devminor> are the
3082 device major and minor numbers, only used when creating block
3083 and character special devices.
3085 Note that, just like L<mknod(2)>, the mode must be bitwise
3086 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3087 just creates a regular file). These constants are
3088 available in the standard Linux header files, or you can use
3089 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3090 which are wrappers around this command which bitwise OR
3091 in the appropriate constant for you.
3093 The mode actually set is affected by the umask.");
3095 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3096 [InitBasicFS, Always, TestOutputStruct (
3097 [["mkfifo"; "0o777"; "/node"];
3098 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3099 "make FIFO (named pipe)",
3101 This call creates a FIFO (named pipe) called C<path> with
3102 mode C<mode>. It is just a convenient wrapper around
3105 The mode actually set is affected by the umask.");
3107 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3108 [InitBasicFS, Always, TestOutputStruct (
3109 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3110 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3111 "make block device node",
3113 This call creates a block device node called C<path> with
3114 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3115 It is just a convenient wrapper around C<guestfs_mknod>.
3117 The mode actually set is affected by the umask.");
3119 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3120 [InitBasicFS, Always, TestOutputStruct (
3121 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3122 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3123 "make char device node",
3125 This call creates a char device node called C<path> with
3126 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3127 It is just a convenient wrapper around C<guestfs_mknod>.
3129 The mode actually set is affected by the umask.");
3131 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3132 [InitEmpty, Always, TestOutputInt (
3133 [["umask"; "0o22"]], 0o22)],
3134 "set file mode creation mask (umask)",
3136 This function sets the mask used for creating new files and
3137 device nodes to C<mask & 0777>.
3139 Typical umask values would be C<022> which creates new files
3140 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3141 C<002> which creates new files with permissions like
3142 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3144 The default umask is C<022>. This is important because it
3145 means that directories and device nodes will be created with
3146 C<0644> or C<0755> mode even if you specify C<0777>.
3148 See also C<guestfs_get_umask>,
3149 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3151 This call returns the previous umask.");
3153 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3155 "read directories entries",
3157 This returns the list of directory entries in directory C<dir>.
3159 All entries in the directory are returned, including C<.> and
3160 C<..>. The entries are I<not> sorted, but returned in the same
3161 order as the underlying filesystem.
3163 Also this call returns basic file type information about each
3164 file. The C<ftyp> field will contain one of the following characters:
3202 The L<readdir(3)> call returned a C<d_type> field with an
3207 This function is primarily intended for use by programs. To
3208 get a simple list of names, use C<guestfs_ls>. To get a printable
3209 directory for human consumption, use C<guestfs_ll>.");
3211 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3213 "create partitions on a block device",
3215 This is a simplified interface to the C<guestfs_sfdisk>
3216 command, where partition sizes are specified in megabytes
3217 only (rounded to the nearest cylinder) and you don't need
3218 to specify the cyls, heads and sectors parameters which
3219 were rarely if ever used anyway.
3221 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3222 and C<guestfs_part_disk>");
3224 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3226 "determine file type inside a compressed file",
3228 This command runs C<file> after first decompressing C<path>
3231 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3233 Since 1.0.63, use C<guestfs_file> instead which can now
3234 process compressed files.");
3236 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3238 "list extended attributes of a file or directory",
3240 This call lists the extended attributes of the file or directory
3243 At the system call level, this is a combination of the
3244 L<listxattr(2)> and L<getxattr(2)> calls.
3246 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3248 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3250 "list extended attributes of a file or directory",
3252 This is the same as C<guestfs_getxattrs>, but if C<path>
3253 is a symbolic link, then it returns the extended attributes
3254 of the link itself.");
3256 ("setxattr", (RErr, [String "xattr";
3257 String "val"; Int "vallen"; (* will be BufferIn *)
3258 Pathname "path"]), 143, [Optional "linuxxattrs"],
3260 "set extended attribute of a file or directory",
3262 This call sets the extended attribute named C<xattr>
3263 of the file C<path> to the value C<val> (of length C<vallen>).
3264 The value is arbitrary 8 bit data.
3266 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3268 ("lsetxattr", (RErr, [String "xattr";
3269 String "val"; Int "vallen"; (* will be BufferIn *)
3270 Pathname "path"]), 144, [Optional "linuxxattrs"],
3272 "set extended attribute of a file or directory",
3274 This is the same as C<guestfs_setxattr>, but if C<path>
3275 is a symbolic link, then it sets an extended attribute
3276 of the link itself.");
3278 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3280 "remove extended attribute of a file or directory",
3282 This call removes the extended attribute named C<xattr>
3283 of the file C<path>.
3285 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3287 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3289 "remove extended attribute of a file or directory",
3291 This is the same as C<guestfs_removexattr>, but if C<path>
3292 is a symbolic link, then it removes an extended attribute
3293 of the link itself.");
3295 ("mountpoints", (RHashtable "mps", []), 147, [],
3299 This call is similar to C<guestfs_mounts>. That call returns
3300 a list of devices. This one returns a hash table (map) of
3301 device name to directory where the device is mounted.");
3303 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3304 (* This is a special case: while you would expect a parameter
3305 * of type "Pathname", that doesn't work, because it implies
3306 * NEED_ROOT in the generated calling code in stubs.c, and
3307 * this function cannot use NEED_ROOT.
3310 "create a mountpoint",
3312 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3313 specialized calls that can be used to create extra mountpoints
3314 before mounting the first filesystem.
3316 These calls are I<only> necessary in some very limited circumstances,
3317 mainly the case where you want to mount a mix of unrelated and/or
3318 read-only filesystems together.
3320 For example, live CDs often contain a \"Russian doll\" nest of
3321 filesystems, an ISO outer layer, with a squashfs image inside, with
3322 an ext2/3 image inside that. You can unpack this as follows
3325 add-ro Fedora-11-i686-Live.iso
3328 mkmountpoint /squash
3331 mount-loop /cd/LiveOS/squashfs.img /squash
3332 mount-loop /squash/LiveOS/ext3fs.img /ext3
3334 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3336 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3338 "remove a mountpoint",
3340 This calls removes a mountpoint that was previously created
3341 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3342 for full details.");
3344 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3345 [InitISOFS, Always, TestOutputBuffer (
3346 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3347 (* Test various near large, large and too large files (RHBZ#589039). *)
3348 InitBasicFS, Always, TestLastFail (
3350 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3351 ["read_file"; "/a"]]);
3352 InitBasicFS, Always, TestLastFail (
3354 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3355 ["read_file"; "/a"]]);
3356 InitBasicFS, Always, TestLastFail (
3358 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3359 ["read_file"; "/a"]])],
3362 This calls returns the contents of the file C<path> as a
3365 Unlike C<guestfs_cat>, this function can correctly
3366 handle files that contain embedded ASCII NUL characters.
3367 However unlike C<guestfs_download>, this function is limited
3368 in the total size of file that can be handled.");
3370 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3371 [InitISOFS, Always, TestOutputList (
3372 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3373 InitISOFS, Always, TestOutputList (
3374 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3375 (* Test for RHBZ#579608, absolute symbolic links. *)
3376 InitISOFS, Always, TestOutputList (
3377 [["grep"; "nomatch"; "/abssymlink"]], [])],
3378 "return lines matching a pattern",
3380 This calls the external C<grep> program and returns the
3383 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3384 [InitISOFS, Always, TestOutputList (
3385 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3386 "return lines matching a pattern",
3388 This calls the external C<egrep> program and returns the
3391 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3392 [InitISOFS, Always, TestOutputList (
3393 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3394 "return lines matching a pattern",
3396 This calls the external C<fgrep> program and returns the
3399 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3400 [InitISOFS, Always, TestOutputList (
3401 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3402 "return lines matching a pattern",
3404 This calls the external C<grep -i> program and returns the
3407 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3408 [InitISOFS, Always, TestOutputList (
3409 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3410 "return lines matching a pattern",
3412 This calls the external C<egrep -i> program and returns the
3415 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3416 [InitISOFS, Always, TestOutputList (
3417 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3418 "return lines matching a pattern",
3420 This calls the external C<fgrep -i> program and returns the
3423 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3424 [InitISOFS, Always, TestOutputList (
3425 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3426 "return lines matching a pattern",
3428 This calls the external C<zgrep> program and returns the
3431 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3432 [InitISOFS, Always, TestOutputList (
3433 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3434 "return lines matching a pattern",
3436 This calls the external C<zegrep> program and returns the
3439 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3440 [InitISOFS, Always, TestOutputList (
3441 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3442 "return lines matching a pattern",
3444 This calls the external C<zfgrep> program and returns the
3447 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3448 [InitISOFS, Always, TestOutputList (
3449 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3450 "return lines matching a pattern",
3452 This calls the external C<zgrep -i> program and returns the
3455 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3456 [InitISOFS, Always, TestOutputList (
3457 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3458 "return lines matching a pattern",
3460 This calls the external C<zegrep -i> program and returns the
3463 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3464 [InitISOFS, Always, TestOutputList (
3465 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3466 "return lines matching a pattern",
3468 This calls the external C<zfgrep -i> program and returns the
3471 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3472 [InitISOFS, Always, TestOutput (
3473 [["realpath"; "/../directory"]], "/directory")],
3474 "canonicalized absolute pathname",
3476 Return the canonicalized absolute pathname of C<path>. The
3477 returned path has no C<.>, C<..> or symbolic link path elements.");
3479 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3480 [InitBasicFS, Always, TestOutputStruct (
3483 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3484 "create a hard link",
3486 This command creates a hard link using the C<ln> command.");
3488 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3489 [InitBasicFS, Always, TestOutputStruct (
3492 ["ln_f"; "/a"; "/b"];
3493 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3494 "create a hard link",
3496 This command creates a hard link using the C<ln -f> command.
3497 The C<-f> option removes the link (C<linkname>) if it exists already.");
3499 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3500 [InitBasicFS, Always, TestOutputStruct (
3502 ["ln_s"; "a"; "/b"];
3503 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3504 "create a symbolic link",
3506 This command creates a symbolic link using the C<ln -s> command.");
3508 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3509 [InitBasicFS, Always, TestOutput (
3510 [["mkdir_p"; "/a/b"];
3511 ["touch"; "/a/b/c"];
3512 ["ln_sf"; "../d"; "/a/b/c"];
3513 ["readlink"; "/a/b/c"]], "../d")],
3514 "create a symbolic link",
3516 This command creates a symbolic link using the C<ln -sf> command,
3517 The C<-f> option removes the link (C<linkname>) if it exists already.");
3519 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3520 [] (* XXX tested above *),
3521 "read the target of a symbolic link",
3523 This command reads the target of a symbolic link.");
3525 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3526 [InitBasicFS, Always, TestOutputStruct (
3527 [["fallocate"; "/a"; "1000000"];
3528 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3529 "preallocate a file in the guest filesystem",
3531 This command preallocates a file (containing zero bytes) named
3532 C<path> of size C<len> bytes. If the file exists already, it
3535 Do not confuse this with the guestfish-specific
3536 C<alloc> command which allocates a file in the host and
3537 attaches it as a device.");
3539 ("swapon_device", (RErr, [Device "device"]), 170, [],
3540 [InitPartition, Always, TestRun (
3541 [["mkswap"; "/dev/sda1"];
3542 ["swapon_device"; "/dev/sda1"];
3543 ["swapoff_device"; "/dev/sda1"]])],
3544 "enable swap on device",
3546 This command enables the libguestfs appliance to use the
3547 swap device or partition named C<device>. The increased
3548 memory is made available for all commands, for example
3549 those run using C<guestfs_command> or C<guestfs_sh>.
3551 Note that you should not swap to existing guest swap
3552 partitions unless you know what you are doing. They may
3553 contain hibernation information, or other information that
3554 the guest doesn't want you to trash. You also risk leaking
3555 information about the host to the guest this way. Instead,
3556 attach a new host device to the guest and swap on that.");
3558 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3559 [], (* XXX tested by swapon_device *)
3560 "disable swap on device",
3562 This command disables the libguestfs appliance swap
3563 device or partition named C<device>.
3564 See C<guestfs_swapon_device>.");
3566 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3567 [InitBasicFS, Always, TestRun (
3568 [["fallocate"; "/swap"; "8388608"];
3569 ["mkswap_file"; "/swap"];
3570 ["swapon_file"; "/swap"];
3571 ["swapoff_file"; "/swap"]])],
3572 "enable swap on file",
3574 This command enables swap to a file.
3575 See C<guestfs_swapon_device> for other notes.");
3577 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3578 [], (* XXX tested by swapon_file *)
3579 "disable swap on file",
3581 This command disables the libguestfs appliance swap on file.");
3583 ("swapon_label", (RErr, [String "label"]), 174, [],
3584 [InitEmpty, Always, TestRun (
3585 [["part_disk"; "/dev/sdb"; "mbr"];
3586 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3587 ["swapon_label"; "swapit"];
3588 ["swapoff_label"; "swapit"];
3589 ["zero"; "/dev/sdb"];
3590 ["blockdev_rereadpt"; "/dev/sdb"]])],
3591 "enable swap on labeled swap partition",
3593 This command enables swap to a labeled swap partition.
3594 See C<guestfs_swapon_device> for other notes.");
3596 ("swapoff_label", (RErr, [String "label"]), 175, [],
3597 [], (* XXX tested by swapon_label *)
3598 "disable swap on labeled swap partition",
3600 This command disables the libguestfs appliance swap on
3601 labeled swap partition.");
3603 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3604 (let uuid = uuidgen () in
3605 [InitEmpty, Always, TestRun (
3606 [["mkswap_U"; uuid; "/dev/sdb"];
3607 ["swapon_uuid"; uuid];
3608 ["swapoff_uuid"; uuid]])]),
3609 "enable swap on swap partition by UUID",
3611 This command enables swap to a swap partition with the given UUID.
3612 See C<guestfs_swapon_device> for other notes.");
3614 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3615 [], (* XXX tested by swapon_uuid *)
3616 "disable swap on swap partition by UUID",
3618 This command disables the libguestfs appliance swap partition
3619 with the given UUID.");
3621 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3622 [InitBasicFS, Always, TestRun (
3623 [["fallocate"; "/swap"; "8388608"];
3624 ["mkswap_file"; "/swap"]])],
3625 "create a swap file",
3629 This command just writes a swap file signature to an existing
3630 file. To create the file itself, use something like C<guestfs_fallocate>.");
3632 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3633 [InitISOFS, Always, TestRun (
3634 [["inotify_init"; "0"]])],
3635 "create an inotify handle",
3637 This command creates a new inotify handle.
3638 The inotify subsystem can be used to notify events which happen to
3639 objects in the guest filesystem.
3641 C<maxevents> is the maximum number of events which will be
3642 queued up between calls to C<guestfs_inotify_read> or
3643 C<guestfs_inotify_files>.
3644 If this is passed as C<0>, then the kernel (or previously set)
3645 default is used. For Linux 2.6.29 the default was 16384 events.
3646 Beyond this limit, the kernel throws away events, but records
3647 the fact that it threw them away by setting a flag
3648 C<IN_Q_OVERFLOW> in the returned structure list (see
3649 C<guestfs_inotify_read>).
3651 Before any events are generated, you have to add some
3652 watches to the internal watch list. See:
3653 C<guestfs_inotify_add_watch>,
3654 C<guestfs_inotify_rm_watch> and
3655 C<guestfs_inotify_watch_all>.
3657 Queued up events should be read periodically by calling
3658 C<guestfs_inotify_read>
3659 (or C<guestfs_inotify_files> which is just a helpful
3660 wrapper around C<guestfs_inotify_read>). If you don't
3661 read the events out often enough then you risk the internal
3664 The handle should be closed after use by calling
3665 C<guestfs_inotify_close>. This also removes any
3666 watches automatically.
3668 See also L<inotify(7)> for an overview of the inotify interface
3669 as exposed by the Linux kernel, which is roughly what we expose
3670 via libguestfs. Note that there is one global inotify handle
3671 per libguestfs instance.");
3673 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3674 [InitBasicFS, Always, TestOutputList (
3675 [["inotify_init"; "0"];
3676 ["inotify_add_watch"; "/"; "1073741823"];
3679 ["inotify_files"]], ["a"; "b"])],
3680 "add an inotify watch",
3682 Watch C<path> for the events listed in C<mask>.
3684 Note that if C<path> is a directory then events within that
3685 directory are watched, but this does I<not> happen recursively
3686 (in subdirectories).
3688 Note for non-C or non-Linux callers: the inotify events are
3689 defined by the Linux kernel ABI and are listed in
3690 C</usr/include/sys/inotify.h>.");
3692 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3694 "remove an inotify watch",
3696 Remove a previously defined inotify watch.
3697 See C<guestfs_inotify_add_watch>.");
3699 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3701 "return list of inotify events",
3703 Return the complete queue of events that have happened
3704 since the previous read call.
3706 If no events have happened, this returns an empty list.
3708 I<Note>: In order to make sure that all events have been
3709 read, you must call this function repeatedly until it
3710 returns an empty list. The reason is that the call will
3711 read events up to the maximum appliance-to-host message
3712 size and leave remaining events in the queue.");
3714 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3716 "return list of watched files that had events",
3718 This function is a helpful wrapper around C<guestfs_inotify_read>
3719 which just returns a list of pathnames of objects that were
3720 touched. The returned pathnames are sorted and deduplicated.");
3722 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3724 "close the inotify handle",
3726 This closes the inotify handle which was previously
3727 opened by inotify_init. It removes all watches, throws
3728 away any pending events, and deallocates all resources.");
3730 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3732 "set SELinux security context",
3734 This sets the SELinux security context of the daemon
3735 to the string C<context>.
3737 See the documentation about SELINUX in L<guestfs(3)>.");
3739 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3741 "get SELinux security context",
3743 This gets the SELinux security context of the daemon.
3745 See the documentation about SELINUX in L<guestfs(3)>,
3746 and C<guestfs_setcon>");
3748 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3749 [InitEmpty, Always, TestOutput (
3750 [["part_disk"; "/dev/sda"; "mbr"];
3751 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3752 ["mount_options"; ""; "/dev/sda1"; "/"];
3753 ["write"; "/new"; "new file contents"];
3754 ["cat"; "/new"]], "new file contents");
3755 InitEmpty, Always, TestRun (
3756 [["part_disk"; "/dev/sda"; "mbr"];
3757 ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3758 InitEmpty, Always, TestLastFail (
3759 [["part_disk"; "/dev/sda"; "mbr"];
3760 ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3761 InitEmpty, Always, TestLastFail (
3762 [["part_disk"; "/dev/sda"; "mbr"];
3763 ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3764 InitEmpty, IfAvailable "ntfsprogs", TestRun (
3765 [["part_disk"; "/dev/sda"; "mbr"];
3766 ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3767 "make a filesystem with block size",
3769 This call is similar to C<guestfs_mkfs>, but it allows you to
3770 control the block size of the resulting filesystem. Supported
3771 block sizes depend on the filesystem type, but typically they
3772 are C<1024>, C<2048> or C<4096> only.
3774 For VFAT and NTFS the C<blocksize> parameter is treated as
3775 the requested cluster size.");
3777 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3778 [InitEmpty, Always, TestOutput (
3779 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3780 ["mke2journal"; "4096"; "/dev/sda1"];
3781 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3782 ["mount_options"; ""; "/dev/sda2"; "/"];
3783 ["write"; "/new"; "new file contents"];
3784 ["cat"; "/new"]], "new file contents")],
3785 "make ext2/3/4 external journal",
3787 This creates an ext2 external journal on C<device>. It is equivalent
3790 mke2fs -O journal_dev -b blocksize device");
3792 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3793 [InitEmpty, Always, TestOutput (
3794 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3795 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3796 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3797 ["mount_options"; ""; "/dev/sda2"; "/"];
3798 ["write"; "/new"; "new file contents"];
3799 ["cat"; "/new"]], "new file contents")],
3800 "make ext2/3/4 external journal with label",
3802 This creates an ext2 external journal on C<device> with label C<label>.");
3804 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3805 (let uuid = uuidgen () in
3806 [InitEmpty, Always, TestOutput (
3807 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3808 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3809 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3810 ["mount_options"; ""; "/dev/sda2"; "/"];
3811 ["write"; "/new"; "new file contents"];
3812 ["cat"; "/new"]], "new file contents")]),
3813 "make ext2/3/4 external journal with UUID",
3815 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3817 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3819 "make ext2/3/4 filesystem with external journal",
3821 This creates an ext2/3/4 filesystem on C<device> with
3822 an external journal on C<journal>. It is equivalent
3825 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3827 See also C<guestfs_mke2journal>.");
3829 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3831 "make ext2/3/4 filesystem with external journal",
3833 This creates an ext2/3/4 filesystem on C<device> with
3834 an external journal on the journal labeled C<label>.
3836 See also C<guestfs_mke2journal_L>.");
3838 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3840 "make ext2/3/4 filesystem with external journal",
3842 This creates an ext2/3/4 filesystem on C<device> with
3843 an external journal on the journal with UUID C<uuid>.
3845 See also C<guestfs_mke2journal_U>.");
3847 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3848 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3849 "load a kernel module",
3851 This loads a kernel module in the appliance.
3853 The kernel module must have been whitelisted when libguestfs
3854 was built (see C<appliance/kmod.whitelist.in> in the source).");
3856 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3857 [InitNone, Always, TestOutput (
3858 [["echo_daemon"; "This is a test"]], "This is a test"
3860 "echo arguments back to the client",
3862 This command concatenates the list of C<words> passed with single spaces
3863 between them and returns the resulting string.
3865 You can use this command to test the connection through to the daemon.
3867 See also C<guestfs_ping_daemon>.");
3869 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3870 [], (* There is a regression test for this. *)
3871 "find all files and directories, returning NUL-separated list",
3873 This command lists out all files and directories, recursively,
3874 starting at C<directory>, placing the resulting list in the
3875 external file called C<files>.
3877 This command works the same way as C<guestfs_find> with the
3878 following exceptions:
3884 The resulting list is written to an external file.
3888 Items (filenames) in the result are separated
3889 by C<\\0> characters. See L<find(1)> option I<-print0>.
3893 This command is not limited in the number of names that it
3898 The result list is not sorted.
3902 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3903 [InitISOFS, Always, TestOutput (
3904 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3905 InitISOFS, Always, TestOutput (
3906 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3907 InitISOFS, Always, TestOutput (
3908 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3909 InitISOFS, Always, TestLastFail (
3910 [["case_sensitive_path"; "/Known-1/"]]);
3911 InitBasicFS, Always, TestOutput (
3913 ["mkdir"; "/a/bbb"];
3914 ["touch"; "/a/bbb/c"];
3915 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3916 InitBasicFS, Always, TestOutput (
3918 ["mkdir"; "/a/bbb"];
3919 ["touch"; "/a/bbb/c"];
3920 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3921 InitBasicFS, Always, TestLastFail (
3923 ["mkdir"; "/a/bbb"];
3924 ["touch"; "/a/bbb/c"];
3925 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3926 "return true path on case-insensitive filesystem",
3928 This can be used to resolve case insensitive paths on
3929 a filesystem which is case sensitive. The use case is
3930 to resolve paths which you have read from Windows configuration
3931 files or the Windows Registry, to the true path.
3933 The command handles a peculiarity of the Linux ntfs-3g
3934 filesystem driver (and probably others), which is that although
3935 the underlying filesystem is case-insensitive, the driver
3936 exports the filesystem to Linux as case-sensitive.
3938 One consequence of this is that special directories such
3939 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3940 (or other things) depending on the precise details of how
3941 they were created. In Windows itself this would not be
3944 Bug or feature? You decide:
3945 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3947 This function resolves the true case of each element in the
3948 path and returns the case-sensitive path.
3950 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3951 might return C<\"/WINDOWS/system32\"> (the exact return value
3952 would depend on details of how the directories were originally
3953 created under Windows).
3956 This function does not handle drive names, backslashes etc.
3958 See also C<guestfs_realpath>.");
3960 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3961 [InitBasicFS, Always, TestOutput (
3962 [["vfs_type"; "/dev/sda1"]], "ext2")],
3963 "get the Linux VFS type corresponding to a mounted device",
3965 This command gets the filesystem type corresponding to
3966 the filesystem on C<device>.
3968 For most filesystems, the result is the name of the Linux
3969 VFS module which would be used to mount this filesystem
3970 if you mounted it without specifying the filesystem type.
3971 For example a string such as C<ext3> or C<ntfs>.");
3973 ("truncate", (RErr, [Pathname "path"]), 199, [],
3974 [InitBasicFS, Always, TestOutputStruct (
3975 [["write"; "/test"; "some stuff so size is not zero"];
3976 ["truncate"; "/test"];
3977 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3978 "truncate a file to zero size",
3980 This command truncates C<path> to a zero-length file. The
3981 file must exist already.");
3983 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3984 [InitBasicFS, Always, TestOutputStruct (
3985 [["touch"; "/test"];
3986 ["truncate_size"; "/test"; "1000"];
3987 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3988 "truncate a file to a particular size",
3990 This command truncates C<path> to size C<size> bytes. The file
3993 If the current file size is less than C<size> then
3994 the file is extended to the required size with zero bytes.
3995 This creates a sparse file (ie. disk blocks are not allocated
3996 for the file until you write to it). To create a non-sparse
3997 file of zeroes, use C<guestfs_fallocate64> instead.");
3999 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
4000 [InitBasicFS, Always, TestOutputStruct (
4001 [["touch"; "/test"];
4002 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
4003 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
4004 "set timestamp of a file with nanosecond precision",
4006 This command sets the timestamps of a file with nanosecond
4009 C<atsecs, atnsecs> are the last access time (atime) in secs and
4010 nanoseconds from the epoch.
4012 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4013 secs and nanoseconds from the epoch.
4015 If the C<*nsecs> field contains the special value C<-1> then
4016 the corresponding timestamp is set to the current time. (The
4017 C<*secs> field is ignored in this case).
4019 If the C<*nsecs> field contains the special value C<-2> then
4020 the corresponding timestamp is left unchanged. (The
4021 C<*secs> field is ignored in this case).");
4023 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4024 [InitBasicFS, Always, TestOutputStruct (
4025 [["mkdir_mode"; "/test"; "0o111"];
4026 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4027 "create a directory with a particular mode",
4029 This command creates a directory, setting the initial permissions
4030 of the directory to C<mode>.
4032 For common Linux filesystems, the actual mode which is set will
4033 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
4034 interpret the mode in other ways.
4036 See also C<guestfs_mkdir>, C<guestfs_umask>");
4038 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4040 "change file owner and group",
4042 Change the file owner to C<owner> and group to C<group>.
4043 This is like C<guestfs_chown> but if C<path> is a symlink then
4044 the link itself is changed, not the target.
4046 Only numeric uid and gid are supported. If you want to use
4047 names, you will need to locate and parse the password file
4048 yourself (Augeas support makes this relatively easy).");
4050 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4052 "lstat on multiple files",
4054 This call allows you to perform the C<guestfs_lstat> operation
4055 on multiple files, where all files are in the directory C<path>.
4056 C<names> is the list of files from this directory.
4058 On return you get a list of stat structs, with a one-to-one
4059 correspondence to the C<names> list. If any name did not exist
4060 or could not be lstat'd, then the C<ino> field of that structure
4063 This call is intended for programs that want to efficiently
4064 list a directory contents without making many round-trips.
4065 See also C<guestfs_lxattrlist> for a similarly efficient call
4066 for getting extended attributes. Very long directory listings
4067 might cause the protocol message size to be exceeded, causing
4068 this call to fail. The caller must split up such requests
4069 into smaller groups of names.");
4071 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4073 "lgetxattr on multiple files",
4075 This call allows you to get the extended attributes
4076 of multiple files, where all files are in the directory C<path>.
4077 C<names> is the list of files from this directory.
4079 On return you get a flat list of xattr structs which must be
4080 interpreted sequentially. The first xattr struct always has a zero-length
4081 C<attrname>. C<attrval> in this struct is zero-length
4082 to indicate there was an error doing C<lgetxattr> for this
4083 file, I<or> is a C string which is a decimal number
4084 (the number of following attributes for this file, which could
4085 be C<\"0\">). Then after the first xattr struct are the
4086 zero or more attributes for the first named file.
4087 This repeats for the second and subsequent files.
4089 This call is intended for programs that want to efficiently
4090 list a directory contents without making many round-trips.
4091 See also C<guestfs_lstatlist> for a similarly efficient call
4092 for getting standard stats. Very long directory listings
4093 might cause the protocol message size to be exceeded, causing
4094 this call to fail. The caller must split up such requests
4095 into smaller groups of names.");
4097 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4099 "readlink on multiple files",
4101 This call allows you to do a C<readlink> operation
4102 on multiple files, where all files are in the directory C<path>.
4103 C<names> is the list of files from this directory.
4105 On return you get a list of strings, with a one-to-one
4106 correspondence to the C<names> list. Each string is the
4107 value of the symbolic link.
4109 If the C<readlink(2)> operation fails on any name, then
4110 the corresponding result string is the empty string C<\"\">.
4111 However the whole operation is completed even if there
4112 were C<readlink(2)> errors, and so you can call this
4113 function with names where you don't know if they are
4114 symbolic links already (albeit slightly less efficient).
4116 This call is intended for programs that want to efficiently
4117 list a directory contents without making many round-trips.
4118 Very long directory listings might cause the protocol
4119 message size to be exceeded, causing
4120 this call to fail. The caller must split up such requests
4121 into smaller groups of names.");
4123 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4124 [InitISOFS, Always, TestOutputBuffer (
4125 [["pread"; "/known-4"; "1"; "3"]], "\n");
4126 InitISOFS, Always, TestOutputBuffer (
4127 [["pread"; "/empty"; "0"; "100"]], "")],
4128 "read part of a file",
4130 This command lets you read part of a file. It reads C<count>
4131 bytes of the file, starting at C<offset>, from file C<path>.
4133 This may read fewer bytes than requested. For further details
4134 see the L<pread(2)> system call.
4136 See also C<guestfs_pwrite>.");
4138 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4139 [InitEmpty, Always, TestRun (
4140 [["part_init"; "/dev/sda"; "gpt"]])],
4141 "create an empty partition table",
4143 This creates an empty partition table on C<device> of one of the
4144 partition types listed below. Usually C<parttype> should be
4145 either C<msdos> or C<gpt> (for large disks).
4147 Initially there are no partitions. Following this, you should
4148 call C<guestfs_part_add> for each partition required.
4150 Possible values for C<parttype> are:
4154 =item B<efi> | B<gpt>
4156 Intel EFI / GPT partition table.
4158 This is recommended for >= 2 TB partitions that will be accessed
4159 from Linux and Intel-based Mac OS X. It also has limited backwards
4160 compatibility with the C<mbr> format.
4162 =item B<mbr> | B<msdos>
4164 The standard PC \"Master Boot Record\" (MBR) format used
4165 by MS-DOS and Windows. This partition type will B<only> work
4166 for device sizes up to 2 TB. For large disks we recommend
4171 Other partition table types that may work but are not
4180 =item B<amiga> | B<rdb>
4182 Amiga \"Rigid Disk Block\" format.
4190 DASD, used on IBM mainframes.
4198 Old Mac partition format. Modern Macs use C<gpt>.
4202 NEC PC-98 format, common in Japan apparently.
4210 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4211 [InitEmpty, Always, TestRun (
4212 [["part_init"; "/dev/sda"; "mbr"];
4213 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4214 InitEmpty, Always, TestRun (
4215 [["part_init"; "/dev/sda"; "gpt"];
4216 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4217 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4218 InitEmpty, Always, TestRun (
4219 [["part_init"; "/dev/sda"; "mbr"];
4220 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4221 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4222 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4223 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4224 "add a partition to the device",
4226 This command adds a partition to C<device>. If there is no partition
4227 table on the device, call C<guestfs_part_init> first.
4229 The C<prlogex> parameter is the type of partition. Normally you
4230 should pass C<p> or C<primary> here, but MBR partition tables also
4231 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4234 C<startsect> and C<endsect> are the start and end of the partition
4235 in I<sectors>. C<endsect> may be negative, which means it counts
4236 backwards from the end of the disk (C<-1> is the last sector).
4238 Creating a partition which covers the whole disk is not so easy.
4239 Use C<guestfs_part_disk> to do that.");
4241 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4242 [InitEmpty, Always, TestRun (
4243 [["part_disk"; "/dev/sda"; "mbr"]]);
4244 InitEmpty, Always, TestRun (
4245 [["part_disk"; "/dev/sda"; "gpt"]])],
4246 "partition whole disk with a single primary partition",
4248 This command is simply a combination of C<guestfs_part_init>
4249 followed by C<guestfs_part_add> to create a single primary partition
4250 covering the whole disk.
4252 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4253 but other possible values are described in C<guestfs_part_init>.");
4255 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4256 [InitEmpty, Always, TestRun (
4257 [["part_disk"; "/dev/sda"; "mbr"];
4258 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4259 "make a partition bootable",
4261 This sets the bootable flag on partition numbered C<partnum> on
4262 device C<device>. Note that partitions are numbered from 1.
4264 The bootable flag is used by some operating systems (notably
4265 Windows) to determine which partition to boot from. It is by
4266 no means universally recognized.");
4268 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4269 [InitEmpty, Always, TestRun (
4270 [["part_disk"; "/dev/sda"; "gpt"];
4271 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4272 "set partition name",
4274 This sets the partition name on partition numbered C<partnum> on
4275 device C<device>. Note that partitions are numbered from 1.
4277 The partition name can only be set on certain types of partition
4278 table. This works on C<gpt> but not on C<mbr> partitions.");
4280 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4281 [], (* XXX Add a regression test for this. *)
4282 "list partitions on a device",
4284 This command parses the partition table on C<device> and
4285 returns the list of partitions found.
4287 The fields in the returned structure are:
4293 Partition number, counting from 1.
4297 Start of the partition I<in bytes>. To get sectors you have to
4298 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4302 End of the partition in bytes.
4306 Size of the partition in bytes.
4310 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4311 [InitEmpty, Always, TestOutput (
4312 [["part_disk"; "/dev/sda"; "gpt"];
4313 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4314 "get the partition table type",
4316 This command examines the partition table on C<device> and
4317 returns the partition table type (format) being used.
4319 Common return values include: C<msdos> (a DOS/Windows style MBR
4320 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4321 values are possible, although unusual. See C<guestfs_part_init>
4324 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4325 [InitBasicFS, Always, TestOutputBuffer (
4326 [["fill"; "0x63"; "10"; "/test"];
4327 ["read_file"; "/test"]], "cccccccccc")],
4328 "fill a file with octets",
4330 This command creates a new file called C<path>. The initial
4331 content of the file is C<len> octets of C<c>, where C<c>
4332 must be a number in the range C<[0..255]>.
4334 To fill a file with zero bytes (sparsely), it is
4335 much more efficient to use C<guestfs_truncate_size>.
4336 To create a file with a pattern of repeating bytes
4337 use C<guestfs_fill_pattern>.");
4339 ("available", (RErr, [StringList "groups"]), 216, [],
4340 [InitNone, Always, TestRun [["available"; ""]]],
4341 "test availability of some parts of the API",
4343 This command is used to check the availability of some
4344 groups of functionality in the appliance, which not all builds of
4345 the libguestfs appliance will be able to provide.
4347 The libguestfs groups, and the functions that those
4348 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4349 You can also fetch this list at runtime by calling
4350 C<guestfs_available_all_groups>.
4352 The argument C<groups> is a list of group names, eg:
4353 C<[\"inotify\", \"augeas\"]> would check for the availability of
4354 the Linux inotify functions and Augeas (configuration file
4357 The command returns no error if I<all> requested groups are available.
4359 It fails with an error if one or more of the requested
4360 groups is unavailable in the appliance.
4362 If an unknown group name is included in the
4363 list of groups then an error is always returned.
4371 You must call C<guestfs_launch> before calling this function.
4373 The reason is because we don't know what groups are
4374 supported by the appliance/daemon until it is running and can
4379 If a group of functions is available, this does not necessarily
4380 mean that they will work. You still have to check for errors
4381 when calling individual API functions even if they are
4386 It is usually the job of distro packagers to build
4387 complete functionality into the libguestfs appliance.
4388 Upstream libguestfs, if built from source with all
4389 requirements satisfied, will support everything.
4393 This call was added in version C<1.0.80>. In previous
4394 versions of libguestfs all you could do would be to speculatively
4395 execute a command to find out if the daemon implemented it.
4396 See also C<guestfs_version>.
4400 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4401 [InitBasicFS, Always, TestOutputBuffer (
4402 [["write"; "/src"; "hello, world"];
4403 ["dd"; "/src"; "/dest"];
4404 ["read_file"; "/dest"]], "hello, world")],
4405 "copy from source to destination using dd",
4407 This command copies from one source device or file C<src>
4408 to another destination device or file C<dest>. Normally you
4409 would use this to copy to or from a device or partition, for
4410 example to duplicate a filesystem.
4412 If the destination is a device, it must be as large or larger
4413 than the source file or device, otherwise the copy will fail.
4414 This command cannot do partial copies (see C<guestfs_copy_size>).");
4416 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4417 [InitBasicFS, Always, TestOutputInt (
4418 [["write"; "/file"; "hello, world"];
4419 ["filesize"; "/file"]], 12)],
4420 "return the size of the file in bytes",
4422 This command returns the size of C<file> in bytes.
4424 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4425 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4426 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4428 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4429 [InitBasicFSonLVM, Always, TestOutputList (
4430 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4431 ["lvs"]], ["/dev/VG/LV2"])],
4432 "rename an LVM logical volume",
4434 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4436 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4437 [InitBasicFSonLVM, Always, TestOutputList (
4439 ["vg_activate"; "false"; "VG"];
4440 ["vgrename"; "VG"; "VG2"];
4441 ["vg_activate"; "true"; "VG2"];
4442 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4443 ["vgs"]], ["VG2"])],
4444 "rename an LVM volume group",
4446 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4448 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4449 [InitISOFS, Always, TestOutputBuffer (
4450 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4451 "list the contents of a single file in an initrd",
4453 This command unpacks the file C<filename> from the initrd file
4454 called C<initrdpath>. The filename must be given I<without> the
4455 initial C</> character.
4457 For example, in guestfish you could use the following command
4458 to examine the boot script (usually called C</init>)
4459 contained in a Linux initrd or initramfs image:
4461 initrd-cat /boot/initrd-<version>.img init
4463 See also C<guestfs_initrd_list>.");
4465 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4467 "get the UUID of a physical volume",
4469 This command returns the UUID of the LVM PV C<device>.");
4471 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4473 "get the UUID of a volume group",
4475 This command returns the UUID of the LVM VG named C<vgname>.");
4477 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4479 "get the UUID of a logical volume",
4481 This command returns the UUID of the LVM LV C<device>.");
4483 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4485 "get the PV UUIDs containing the volume group",
4487 Given a VG called C<vgname>, this returns the UUIDs of all
4488 the physical volumes that this volume group resides on.
4490 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4491 calls to associate physical volumes and volume groups.
4493 See also C<guestfs_vglvuuids>.");
4495 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4497 "get the LV UUIDs of all LVs in the volume group",
4499 Given a VG called C<vgname>, this returns the UUIDs of all
4500 the logical volumes created in this volume group.
4502 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4503 calls to associate logical volumes and volume groups.
4505 See also C<guestfs_vgpvuuids>.");
4507 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4508 [InitBasicFS, Always, TestOutputBuffer (
4509 [["write"; "/src"; "hello, world"];
4510 ["copy_size"; "/src"; "/dest"; "5"];
4511 ["read_file"; "/dest"]], "hello")],
4512 "copy size bytes from source to destination using dd",
4514 This command copies exactly C<size> bytes from one source device
4515 or file C<src> to another destination device or file C<dest>.
4517 Note this will fail if the source is too short or if the destination
4518 is not large enough.");
4520 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4521 [InitBasicFSonLVM, Always, TestRun (
4522 [["zero_device"; "/dev/VG/LV"]])],
4523 "write zeroes to an entire device",
4525 This command writes zeroes over the entire C<device>. Compare
4526 with C<guestfs_zero> which just zeroes the first few blocks of
4529 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4530 [InitBasicFS, Always, TestOutput (
4531 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4532 ["cat"; "/hello"]], "hello\n")],
4533 "unpack compressed tarball to directory",
4535 This command uploads and unpacks local file C<tarball> (an
4536 I<xz compressed> tar file) into C<directory>.");
4538 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4540 "pack directory into compressed tarball",
4542 This command packs the contents of C<directory> and downloads
4543 it to local file C<tarball> (as an xz compressed tar archive).");
4545 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4547 "resize an NTFS filesystem",
4549 This command resizes an NTFS filesystem, expanding or
4550 shrinking it to the size of the underlying device.
4551 See also L<ntfsresize(8)>.");
4553 ("vgscan", (RErr, []), 232, [],
4554 [InitEmpty, Always, TestRun (
4556 "rescan for LVM physical volumes, volume groups and logical volumes",
4558 This rescans all block devices and rebuilds the list of LVM
4559 physical volumes, volume groups and logical volumes.");
4561 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4562 [InitEmpty, Always, TestRun (
4563 [["part_init"; "/dev/sda"; "mbr"];
4564 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4565 ["part_del"; "/dev/sda"; "1"]])],
4566 "delete a partition",
4568 This command deletes the partition numbered C<partnum> on C<device>.
4570 Note that in the case of MBR partitioning, deleting an
4571 extended partition also deletes any logical partitions
4574 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4575 [InitEmpty, Always, TestOutputTrue (
4576 [["part_init"; "/dev/sda"; "mbr"];
4577 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4578 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4579 ["part_get_bootable"; "/dev/sda"; "1"]])],
4580 "return true if a partition is bootable",
4582 This command returns true if the partition C<partnum> on
4583 C<device> has the bootable flag set.
4585 See also C<guestfs_part_set_bootable>.");
4587 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4588 [InitEmpty, Always, TestOutputInt (
4589 [["part_init"; "/dev/sda"; "mbr"];
4590 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4591 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4592 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4593 "get the MBR type byte (ID byte) from a partition",
4595 Returns the MBR type byte (also known as the ID byte) from
4596 the numbered partition C<partnum>.
4598 Note that only MBR (old DOS-style) partitions have type bytes.
4599 You will get undefined results for other partition table
4600 types (see C<guestfs_part_get_parttype>).");
4602 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4603 [], (* tested by part_get_mbr_id *)
4604 "set the MBR type byte (ID byte) of a partition",
4606 Sets the MBR type byte (also known as the ID byte) of
4607 the numbered partition C<partnum> to C<idbyte>. Note
4608 that the type bytes quoted in most documentation are
4609 in fact hexadecimal numbers, but usually documented
4610 without any leading \"0x\" which might be confusing.
4612 Note that only MBR (old DOS-style) partitions have type bytes.
4613 You will get undefined results for other partition table
4614 types (see C<guestfs_part_get_parttype>).");
4616 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4617 [InitISOFS, Always, TestOutput (
4618 [["checksum_device"; "md5"; "/dev/sdd"]],
4619 (Digest.to_hex (Digest.file "images/test.iso")))],
4620 "compute MD5, SHAx or CRC checksum of the contents of a device",
4622 This call computes the MD5, SHAx or CRC checksum of the
4623 contents of the device named C<device>. For the types of
4624 checksums supported see the C<guestfs_checksum> command.");
4626 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4627 [InitNone, Always, TestRun (
4628 [["part_disk"; "/dev/sda"; "mbr"];
4629 ["pvcreate"; "/dev/sda1"];
4630 ["vgcreate"; "VG"; "/dev/sda1"];
4631 ["lvcreate"; "LV"; "VG"; "10"];
4632 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4633 "expand an LV to fill free space",
4635 This expands an existing logical volume C<lv> so that it fills
4636 C<pc>% of the remaining free space in the volume group. Commonly
4637 you would call this with pc = 100 which expands the logical volume
4638 as much as possible, using all remaining free space in the volume
4641 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4642 [], (* XXX Augeas code needs tests. *)
4643 "clear Augeas path",
4645 Set the value associated with C<path> to C<NULL>. This
4646 is the same as the L<augtool(1)> C<clear> command.");
4648 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4649 [InitEmpty, Always, TestOutputInt (
4650 [["get_umask"]], 0o22)],
4651 "get the current umask",
4653 Return the current umask. By default the umask is C<022>
4654 unless it has been set by calling C<guestfs_umask>.");
4656 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4658 "upload a file to the appliance (internal use only)",
4660 The C<guestfs_debug_upload> command uploads a file to
4661 the libguestfs appliance.
4663 There is no comprehensive help for this command. You have
4664 to look at the file C<daemon/debug.c> in the libguestfs source
4665 to find out what it is for.");
4667 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4668 [InitBasicFS, Always, TestOutput (
4669 [["base64_in"; "../images/hello.b64"; "/hello"];
4670 ["cat"; "/hello"]], "hello\n")],
4671 "upload base64-encoded data to file",
4673 This command uploads base64-encoded data from C<base64file>
4676 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4678 "download file and encode as base64",
4680 This command downloads the contents of C<filename>, writing
4681 it out to local file C<base64file> encoded as base64.");
4683 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4685 "compute MD5, SHAx or CRC checksum of files in a directory",
4687 This command computes the checksums of all regular files in
4688 C<directory> and then emits a list of those checksums to
4689 the local output file C<sumsfile>.
4691 This can be used for verifying the integrity of a virtual
4692 machine. However to be properly secure you should pay
4693 attention to the output of the checksum command (it uses
4694 the ones from GNU coreutils). In particular when the
4695 filename is not printable, coreutils uses a special
4696 backslash syntax. For more information, see the GNU
4697 coreutils info file.");
4699 ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4700 [InitBasicFS, Always, TestOutputBuffer (
4701 [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4702 ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4703 "fill a file with a repeating pattern of bytes",
4705 This function is like C<guestfs_fill> except that it creates
4706 a new file of length C<len> containing the repeating pattern
4707 of bytes in C<pattern>. The pattern is truncated if necessary
4708 to ensure the length of the file is exactly C<len> bytes.");
4710 ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4711 [InitBasicFS, Always, TestOutput (
4712 [["write"; "/new"; "new file contents"];
4713 ["cat"; "/new"]], "new file contents");
4714 InitBasicFS, Always, TestOutput (
4715 [["write"; "/new"; "\nnew file contents\n"];
4716 ["cat"; "/new"]], "\nnew file contents\n");
4717 InitBasicFS, Always, TestOutput (
4718 [["write"; "/new"; "\n\n"];
4719 ["cat"; "/new"]], "\n\n");
4720 InitBasicFS, Always, TestOutput (
4721 [["write"; "/new"; ""];
4722 ["cat"; "/new"]], "");
4723 InitBasicFS, Always, TestOutput (
4724 [["write"; "/new"; "\n\n\n"];
4725 ["cat"; "/new"]], "\n\n\n");
4726 InitBasicFS, Always, TestOutput (
4727 [["write"; "/new"; "\n"];
4728 ["cat"; "/new"]], "\n")],
4729 "create a new file",
4731 This call creates a file called C<path>. The content of the
4732 file is the string C<content> (which can contain any 8 bit data).");
4734 ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4735 [InitBasicFS, Always, TestOutput (
4736 [["write"; "/new"; "new file contents"];
4737 ["pwrite"; "/new"; "data"; "4"];
4738 ["cat"; "/new"]], "new data contents");
4739 InitBasicFS, Always, TestOutput (
4740 [["write"; "/new"; "new file contents"];
4741 ["pwrite"; "/new"; "is extended"; "9"];
4742 ["cat"; "/new"]], "new file is extended");
4743 InitBasicFS, Always, TestOutput (
4744 [["write"; "/new"; "new file contents"];
4745 ["pwrite"; "/new"; ""; "4"];
4746 ["cat"; "/new"]], "new file contents")],
4747 "write to part of a file",
4749 This command writes to part of a file. It writes the data
4750 buffer C<content> to the file C<path> starting at offset C<offset>.
4752 This command implements the L<pwrite(2)> system call, and like
4753 that system call it may not write the full data requested. The
4754 return value is the number of bytes that were actually written
4755 to the file. This could even be 0, although short writes are
4756 unlikely for regular files in ordinary circumstances.
4758 See also C<guestfs_pread>.");
4760 ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4762 "resize an ext2, ext3 or ext4 filesystem (with size)",
4764 This command is the same as C<guestfs_resize2fs> except that it
4765 allows you to specify the new size (in bytes) explicitly.");
4767 ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4769 "resize an LVM physical volume (with size)",
4771 This command is the same as C<guestfs_pvresize> except that it
4772 allows you to specify the new size (in bytes) explicitly.");
4774 ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4776 "resize an NTFS filesystem (with size)",
4778 This command is the same as C<guestfs_ntfsresize> except that it
4779 allows you to specify the new size (in bytes) explicitly.");
4781 ("available_all_groups", (RStringList "groups", []), 251, [],
4782 [InitNone, Always, TestRun [["available_all_groups"]]],
4783 "return a list of all optional groups",
4785 This command returns a list of all optional groups that this
4786 daemon knows about. Note this returns both supported and unsupported
4787 groups. To find out which ones the daemon can actually support
4788 you have to call C<guestfs_available> on each member of the
4791 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4793 ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4794 [InitBasicFS, Always, TestOutputStruct (
4795 [["fallocate64"; "/a"; "1000000"];
4796 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4797 "preallocate a file in the guest filesystem",
4799 This command preallocates a file (containing zero bytes) named
4800 C<path> of size C<len> bytes. If the file exists already, it
4803 Note that this call allocates disk blocks for the file.
4804 To create a sparse file use C<guestfs_truncate_size> instead.
4806 The deprecated call C<guestfs_fallocate> does the same,
4807 but owing to an oversight it only allowed 30 bit lengths
4808 to be specified, effectively limiting the maximum size
4809 of files created through that call to 1GB.
4811 Do not confuse this with the guestfish-specific
4812 C<alloc> and C<sparse> commands which create
4813 a file in the host and attach it as a device.");
4815 ("vfs_label", (RString "label", [Device "device"]), 253, [],
4816 [InitBasicFS, Always, TestOutput (
4817 [["set_e2label"; "/dev/sda1"; "LTEST"];
4818 ["vfs_label"; "/dev/sda1"]], "LTEST")],
4819 "get the filesystem label",
4821 This returns the filesystem label of the filesystem on
4824 If the filesystem is unlabeled, this returns the empty string.");
4826 ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4827 (let uuid = uuidgen () in
4828 [InitBasicFS, Always, TestOutput (
4829 [["set_e2uuid"; "/dev/sda1"; uuid];
4830 ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4831 "get the filesystem UUID",
4833 This returns the filesystem UUID of the filesystem on
4836 If the filesystem does not have a UUID, this returns the empty string.");
4840 let all_functions = non_daemon_functions @ daemon_functions
4842 (* In some places we want the functions to be displayed sorted
4843 * alphabetically, so this is useful:
4845 let all_functions_sorted =
4846 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4847 compare n1 n2) all_functions
4849 (* This is used to generate the src/MAX_PROC_NR file which
4850 * contains the maximum procedure number, a surrogate for the
4851 * ABI version number. See src/Makefile.am for the details.
4854 let proc_nrs = List.map (
4855 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4856 ) daemon_functions in
4857 List.fold_left max 0 proc_nrs
4859 (* Field types for structures. *)
4861 | FChar (* C 'char' (really, a 7 bit byte). *)
4862 | FString (* nul-terminated ASCII string, NOT NULL. *)
4863 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4868 | FBytes (* Any int measure that counts bytes. *)
4869 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4870 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4872 (* Because we generate extra parsing code for LVM command line tools,
4873 * we have to pull out the LVM columns separately here.
4883 "pv_attr", FString (* XXX *);
4884 "pv_pe_count", FInt64;
4885 "pv_pe_alloc_count", FInt64;
4888 "pv_mda_count", FInt64;
4889 "pv_mda_free", FBytes;
4890 (* Not in Fedora 10:
4891 "pv_mda_size", FBytes;
4898 "vg_attr", FString (* XXX *);
4901 "vg_sysid", FString;
4902 "vg_extent_size", FBytes;
4903 "vg_extent_count", FInt64;
4904 "vg_free_count", FInt64;
4909 "snap_count", FInt64;
4912 "vg_mda_count", FInt64;
4913 "vg_mda_free", FBytes;
4914 (* Not in Fedora 10:
4915 "vg_mda_size", FBytes;
4921 "lv_attr", FString (* XXX *);
4924 "lv_kernel_major", FInt64;
4925 "lv_kernel_minor", FInt64;
4927 "seg_count", FInt64;
4929 "snap_percent", FOptPercent;
4930 "copy_percent", FOptPercent;
4933 "mirror_log", FString;
4937 (* Names and fields in all structures (in RStruct and RStructList)
4941 (* The old RIntBool return type, only ever used for aug_defnode. Do
4942 * not use this struct in any new code.
4945 "i", FInt32; (* for historical compatibility *)
4946 "b", FInt32; (* for historical compatibility *)
4949 (* LVM PVs, VGs, LVs. *)
4950 "lvm_pv", lvm_pv_cols;
4951 "lvm_vg", lvm_vg_cols;
4952 "lvm_lv", lvm_lv_cols;
4954 (* Column names and types from stat structures.
4955 * NB. Can't use things like 'st_atime' because glibc header files
4956 * define some of these as macros. Ugh.
4987 (* Column names in dirent structure. *)
4990 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4995 (* Version numbers. *)
5003 (* Extended attribute. *)
5005 "attrname", FString;
5009 (* Inotify events. *)
5013 "in_cookie", FUInt32;
5017 (* Partition table entry. *)
5020 "part_start", FBytes;
5022 "part_size", FBytes;
5024 ] (* end of structs *)
5026 (* Ugh, Java has to be different ..
5027 * These names are also used by the Haskell bindings.
5029 let java_structs = [
5030 "int_bool", "IntBool";
5035 "statvfs", "StatVFS";
5037 "version", "Version";
5039 "inotify_event", "INotifyEvent";
5040 "partition", "Partition";
5043 (* What structs are actually returned. *)
5044 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5046 (* Returns a list of RStruct/RStructList structs that are returned
5047 * by any function. Each element of returned list is a pair:
5049 * (structname, RStructOnly)
5050 * == there exists function which returns RStruct (_, structname)
5051 * (structname, RStructListOnly)
5052 * == there exists function which returns RStructList (_, structname)
5053 * (structname, RStructAndList)
5054 * == there are functions returning both RStruct (_, structname)
5055 * and RStructList (_, structname)
5057 let rstructs_used_by functions =
5058 (* ||| is a "logical OR" for rstructs_used_t *)
5062 | _, RStructAndList -> RStructAndList
5063 | RStructOnly, RStructListOnly
5064 | RStructListOnly, RStructOnly -> RStructAndList
5065 | RStructOnly, RStructOnly -> RStructOnly
5066 | RStructListOnly, RStructListOnly -> RStructListOnly
5069 let h = Hashtbl.create 13 in
5071 (* if elem->oldv exists, update entry using ||| operator,
5072 * else just add elem->newv to the hash
5074 let update elem newv =
5075 try let oldv = Hashtbl.find h elem in
5076 Hashtbl.replace h elem (newv ||| oldv)
5077 with Not_found -> Hashtbl.add h elem newv
5081 fun (_, style, _, _, _, _, _) ->
5082 match fst style with
5083 | RStruct (_, structname) -> update structname RStructOnly
5084 | RStructList (_, structname) -> update structname RStructListOnly
5088 (* return key->values as a list of (key,value) *)
5089 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5091 (* Used for testing language bindings. *)
5093 | CallString of string
5094 | CallOptString of string option
5095 | CallStringList of string list
5097 | CallInt64 of int64
5099 | CallBuffer of string
5101 (* Used for the guestfish -N (prepared disk images) option.
5102 * Note that the longdescs are indented by 2 spaces.
5106 "create a blank disk",
5107 [ "size", "100M", "the size of the disk image" ],
5108 " Create a blank disk, size 100MB (by default).
5110 The default size can be changed by supplying an optional parameter.");
5113 "create a partitioned disk",
5114 [ "size", "100M", "the size of the disk image";
5115 "partition", "mbr", "partition table type" ],
5116 " Create a disk with a single partition. By default the size of the disk
5117 is 100MB (the available space in the partition will be a tiny bit smaller)
5118 and the partition table will be MBR (old DOS-style).
5120 These defaults can be changed by supplying optional parameters.");
5123 "create a filesystem",
5124 [ "filesystem", "ext2", "the type of filesystem to use";
5125 "size", "100M", "the size of the disk image";
5126 "partition", "mbr", "partition table type" ],
5127 " Create a disk with a single partition, with the partition containing
5128 an empty filesystem. This defaults to creating a 100MB disk (the available
5129 space in the filesystem will be a tiny bit smaller) with an MBR (old
5130 DOS-style) partition table and an ext2 filesystem.
5132 These defaults can be changed by supplying optional parameters.");
5135 (* Used to memoize the result of pod2text. *)
5136 let pod2text_memo_filename = "src/.pod2text.data"
5137 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5139 let chan = open_in pod2text_memo_filename in
5140 let v = input_value chan in
5144 _ -> Hashtbl.create 13
5145 let pod2text_memo_updated () =
5146 let chan = open_out pod2text_memo_filename in
5147 output_value chan pod2text_memo;
5150 (* Useful functions.
5151 * Note we don't want to use any external OCaml libraries which
5152 * makes this a bit harder than it should be.
5154 module StringMap = Map.Make (String)
5156 let failwithf fs = ksprintf failwith fs
5158 let unique = let i = ref 0 in fun () -> incr i; !i
5160 let replace_char s c1 c2 =
5161 let s2 = String.copy s in
5162 let r = ref false in
5163 for i = 0 to String.length s2 - 1 do
5164 if String.unsafe_get s2 i = c1 then (
5165 String.unsafe_set s2 i c2;
5169 if not !r then s else s2
5173 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5175 let triml ?(test = isspace) str =
5177 let n = ref (String.length str) in
5178 while !n > 0 && test str.[!i]; do
5183 else String.sub str !i !n
5185 let trimr ?(test = isspace) str =
5186 let n = ref (String.length str) in
5187 while !n > 0 && test str.[!n-1]; do
5190 if !n = String.length str then str
5191 else String.sub str 0 !n
5193 let trim ?(test = isspace) str =
5194 trimr ~test (triml ~test str)
5196 let rec find s sub =
5197 let len = String.length s in
5198 let sublen = String.length sub in
5200 if i <= len-sublen then (
5202 if j < sublen then (
5203 if s.[i+j] = sub.[j] then loop2 (j+1)
5209 if r = -1 then loop (i+1) else r
5215 let rec replace_str s s1 s2 =
5216 let len = String.length s in
5217 let sublen = String.length s1 in
5218 let i = find s s1 in
5221 let s' = String.sub s 0 i in
5222 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5223 s' ^ s2 ^ replace_str s'' s1 s2
5226 let rec string_split sep str =
5227 let len = String.length str in
5228 let seplen = String.length sep in
5229 let i = find str sep in
5230 if i = -1 then [str]
5232 let s' = String.sub str 0 i in
5233 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5234 s' :: string_split sep s''
5237 let files_equal n1 n2 =
5238 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5239 match Sys.command cmd with
5242 | i -> failwithf "%s: failed with error code %d" cmd i
5244 let rec filter_map f = function
5248 | Some y -> y :: filter_map f xs
5249 | None -> filter_map f xs
5251 let rec find_map f = function
5252 | [] -> raise Not_found
5256 | None -> find_map f xs
5259 let rec loop i = function
5261 | x :: xs -> f i x; loop (i+1) xs
5266 let rec loop i = function
5268 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5272 let count_chars c str =
5273 let count = ref 0 in
5274 for i = 0 to String.length str - 1 do
5275 if c = String.unsafe_get str i then incr count
5281 for i = 0 to String.length str - 1 do
5282 let c = String.unsafe_get str i in
5287 let map_chars f str =
5288 List.map f (explode str)
5290 let name_of_argt = function
5291 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5292 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5293 | FileIn n | FileOut n | BufferIn n -> n
5295 let java_name_of_struct typ =
5296 try List.assoc typ java_structs
5299 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5301 let cols_of_struct typ =
5302 try List.assoc typ structs
5304 failwithf "cols_of_struct: unknown struct %s" typ
5306 let seq_of_test = function
5307 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5308 | TestOutputListOfDevices (s, _)
5309 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5310 | TestOutputTrue s | TestOutputFalse s
5311 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5312 | TestOutputStruct (s, _)
5313 | TestLastFail s -> s
5315 (* Handling for function flags. *)
5316 let protocol_limit_warning =
5317 "Because of the message protocol, there is a transfer limit
5318 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5320 let danger_will_robinson =
5321 "B<This command is dangerous. Without careful use you
5322 can easily destroy all your data>."
5324 let deprecation_notice flags =
5327 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5329 sprintf "This function is deprecated.
5330 In new code, use the C<%s> call instead.
5332 Deprecated functions will not be removed from the API, but the
5333 fact that they are deprecated indicates that there are problems
5334 with correct use of these functions." alt in
5339 (* Create list of optional groups. *)
5341 let h = Hashtbl.create 13 in
5343 fun (name, _, _, flags, _, _, _) ->
5347 let names = try Hashtbl.find h group with Not_found -> [] in
5348 Hashtbl.replace h group (name :: names)
5352 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5355 fun group -> group, List.sort compare (Hashtbl.find h group)
5357 List.sort (fun x y -> compare (fst x) (fst y)) groups
5359 (* Check function names etc. for consistency. *)
5360 let check_functions () =
5361 let contains_uppercase str =
5362 let len = String.length str in
5364 if i >= len then false
5367 if c >= 'A' && c <= 'Z' then true
5374 (* Check function names. *)
5376 fun (name, _, _, _, _, _, _) ->
5377 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5378 failwithf "function name %s does not need 'guestfs' prefix" name;
5380 failwithf "function name is empty";
5381 if name.[0] < 'a' || name.[0] > 'z' then
5382 failwithf "function name %s must start with lowercase a-z" name;
5383 if String.contains name '-' then
5384 failwithf "function name %s should not contain '-', use '_' instead."
5388 (* Check function parameter/return names. *)
5390 fun (name, style, _, _, _, _, _) ->
5391 let check_arg_ret_name n =
5392 if contains_uppercase n then
5393 failwithf "%s param/ret %s should not contain uppercase chars"
5395 if String.contains n '-' || String.contains n '_' then
5396 failwithf "%s param/ret %s should not contain '-' or '_'"
5399 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;
5400 if n = "int" || n = "char" || n = "short" || n = "long" then
5401 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5402 if n = "i" || n = "n" then
5403 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5404 if n = "argv" || n = "args" then
5405 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5407 (* List Haskell, OCaml and C keywords here.
5408 * http://www.haskell.org/haskellwiki/Keywords
5409 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5410 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5411 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5412 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5413 * Omitting _-containing words, since they're handled above.
5414 * Omitting the OCaml reserved word, "val", is ok,
5415 * and saves us from renaming several parameters.
5418 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5419 "char"; "class"; "const"; "constraint"; "continue"; "data";
5420 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5421 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5422 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5423 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5424 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5426 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5427 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5428 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5429 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5430 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5431 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5432 "volatile"; "when"; "where"; "while";
5434 if List.mem n reserved then
5435 failwithf "%s has param/ret using reserved word %s" name n;
5438 (match fst style with
5440 | RInt n | RInt64 n | RBool n
5441 | RConstString n | RConstOptString n | RString n
5442 | RStringList n | RStruct (n, _) | RStructList (n, _)
5443 | RHashtable n | RBufferOut n ->
5444 check_arg_ret_name n
5446 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5449 (* Check short descriptions. *)
5451 fun (name, _, _, _, _, shortdesc, _) ->
5452 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5453 failwithf "short description of %s should begin with lowercase." name;
5454 let c = shortdesc.[String.length shortdesc-1] in
5455 if c = '\n' || c = '.' then
5456 failwithf "short description of %s should not end with . or \\n." name
5459 (* Check long descriptions. *)
5461 fun (name, _, _, _, _, _, longdesc) ->
5462 if longdesc.[String.length longdesc-1] = '\n' then
5463 failwithf "long description of %s should not end with \\n." name
5466 (* Check proc_nrs. *)
5468 fun (name, _, proc_nr, _, _, _, _) ->
5469 if proc_nr <= 0 then
5470 failwithf "daemon function %s should have proc_nr > 0" name
5474 fun (name, _, proc_nr, _, _, _, _) ->
5475 if proc_nr <> -1 then
5476 failwithf "non-daemon function %s should have proc_nr -1" name
5477 ) non_daemon_functions;
5480 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5483 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5484 let rec loop = function
5487 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5489 | (name1,nr1) :: (name2,nr2) :: _ ->
5490 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5498 (* Ignore functions that have no tests. We generate a
5499 * warning when the user does 'make check' instead.
5501 | name, _, _, _, [], _, _ -> ()
5502 | name, _, _, _, tests, _, _ ->
5506 match seq_of_test test with
5508 failwithf "%s has a test containing an empty sequence" name
5509 | cmds -> List.map List.hd cmds
5511 let funcs = List.flatten funcs in
5513 let tested = List.mem name funcs in
5516 failwithf "function %s has tests but does not test itself" name
5519 (* 'pr' prints to the current output file. *)
5520 let chan = ref Pervasives.stdout
5525 let i = count_chars '\n' str in
5526 lines := !lines + i;
5527 output_string !chan str
5530 let copyright_years =
5531 let this_year = 1900 + (localtime (time ())).tm_year in
5532 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5534 (* Generate a header block in a number of standard styles. *)
5535 type comment_style =
5536 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5537 type license = GPLv2plus | LGPLv2plus
5539 let generate_header ?(extra_inputs = []) comment license =
5540 let inputs = "src/generator.ml" :: extra_inputs in
5541 let c = match comment with
5542 | CStyle -> pr "/* "; " *"
5543 | CPlusPlusStyle -> pr "// "; "//"
5544 | HashStyle -> pr "# "; "#"
5545 | OCamlStyle -> pr "(* "; " *"
5546 | HaskellStyle -> pr "{- "; " " in
5547 pr "libguestfs generated file\n";
5548 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5549 List.iter (pr "%s %s\n" c) inputs;
5550 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5552 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5556 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5557 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5558 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5559 pr "%s (at your option) any later version.\n" c;
5561 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5562 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5563 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5564 pr "%s GNU General Public License for more details.\n" c;
5566 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5567 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5568 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5571 pr "%s This library is free software; you can redistribute it and/or\n" c;
5572 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5573 pr "%s License as published by the Free Software Foundation; either\n" c;
5574 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5576 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5577 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5578 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5579 pr "%s Lesser General Public License for more details.\n" c;
5581 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5582 pr "%s License along with this library; if not, write to the Free Software\n" c;
5583 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5586 | CStyle -> pr " */\n"
5589 | OCamlStyle -> pr " *)\n"
5590 | HaskellStyle -> pr "-}\n"
5594 (* Start of main code generation functions below this line. *)
5596 (* Generate the pod documentation for the C API. *)
5597 let rec generate_actions_pod () =
5599 fun (shortname, style, _, flags, _, _, longdesc) ->
5600 if not (List.mem NotInDocs flags) then (
5601 let name = "guestfs_" ^ shortname in
5602 pr "=head2 %s\n\n" name;
5604 generate_prototype ~extern:false ~handle:"g" name style;
5606 pr "%s\n\n" longdesc;
5607 (match fst style with
5609 pr "This function returns 0 on success or -1 on error.\n\n"
5611 pr "On error this function returns -1.\n\n"
5613 pr "On error this function returns -1.\n\n"
5615 pr "This function returns a C truth value on success or -1 on error.\n\n"
5617 pr "This function returns a string, or NULL on error.
5618 The string is owned by the guest handle and must I<not> be freed.\n\n"
5619 | RConstOptString _ ->
5620 pr "This function returns a string which may be NULL.
5621 There is no way to return an error from this function.
5622 The string is owned by the guest handle and must I<not> be freed.\n\n"
5624 pr "This function returns a string, or NULL on error.
5625 I<The caller must free the returned string after use>.\n\n"
5627 pr "This function returns a NULL-terminated array of strings
5628 (like L<environ(3)>), or NULL if there was an error.
5629 I<The caller must free the strings and the array after use>.\n\n"
5630 | RStruct (_, typ) ->
5631 pr "This function returns a C<struct guestfs_%s *>,
5632 or NULL if there was an error.
5633 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5634 | RStructList (_, typ) ->
5635 pr "This function returns a C<struct guestfs_%s_list *>
5636 (see E<lt>guestfs-structs.hE<gt>),
5637 or NULL if there was an error.
5638 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5640 pr "This function returns a NULL-terminated array of
5641 strings, or NULL if there was an error.
5642 The array of strings will always have length C<2n+1>, where
5643 C<n> keys and values alternate, followed by the trailing NULL entry.
5644 I<The caller must free the strings and the array after use>.\n\n"
5646 pr "This function returns a buffer, or NULL on error.
5647 The size of the returned buffer is written to C<*size_r>.
5648 I<The caller must free the returned buffer after use>.\n\n"
5650 if List.mem ProtocolLimitWarning flags then
5651 pr "%s\n\n" protocol_limit_warning;
5652 if List.mem DangerWillRobinson flags then
5653 pr "%s\n\n" danger_will_robinson;
5654 match deprecation_notice flags with
5656 | Some txt -> pr "%s\n\n" txt
5658 ) all_functions_sorted
5660 and generate_structs_pod () =
5661 (* Structs documentation. *)
5664 pr "=head2 guestfs_%s\n" typ;
5666 pr " struct guestfs_%s {\n" typ;
5669 | name, FChar -> pr " char %s;\n" name
5670 | name, FUInt32 -> pr " uint32_t %s;\n" name
5671 | name, FInt32 -> pr " int32_t %s;\n" name
5672 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5673 | name, FInt64 -> pr " int64_t %s;\n" name
5674 | name, FString -> pr " char *%s;\n" name
5676 pr " /* The next two fields describe a byte array. */\n";
5677 pr " uint32_t %s_len;\n" name;
5678 pr " char *%s;\n" name
5680 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5681 pr " char %s[32];\n" name
5682 | name, FOptPercent ->
5683 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5684 pr " float %s;\n" name
5688 pr " struct guestfs_%s_list {\n" typ;
5689 pr " uint32_t len; /* Number of elements in list. */\n";
5690 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5693 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5694 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5699 and generate_availability_pod () =
5700 (* Availability documentation. *)
5704 fun (group, functions) ->
5705 pr "=item B<%s>\n" group;
5707 pr "The following functions:\n";
5708 List.iter (pr "L</guestfs_%s>\n") functions;
5714 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5715 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5717 * We have to use an underscore instead of a dash because otherwise
5718 * rpcgen generates incorrect code.
5720 * This header is NOT exported to clients, but see also generate_structs_h.
5722 and generate_xdr () =
5723 generate_header CStyle LGPLv2plus;
5725 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5726 pr "typedef string guestfs_str<>;\n";
5729 (* Internal structures. *)
5733 pr "struct guestfs_int_%s {\n" typ;
5735 | name, FChar -> pr " char %s;\n" name
5736 | name, FString -> pr " string %s<>;\n" name
5737 | name, FBuffer -> pr " opaque %s<>;\n" name
5738 | name, FUUID -> pr " opaque %s[32];\n" name
5739 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5740 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5741 | name, FOptPercent -> pr " float %s;\n" name
5745 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5750 fun (shortname, style, _, _, _, _, _) ->
5751 let name = "guestfs_" ^ shortname in
5753 (match snd style with
5756 pr "struct %s_args {\n" name;
5759 | Pathname n | Device n | Dev_or_Path n | String n ->
5760 pr " string %s<>;\n" n
5761 | OptString n -> pr " guestfs_str *%s;\n" n
5762 | StringList n | DeviceList n -> pr " guestfs_str %s<>;\n" n
5763 | Bool n -> pr " bool %s;\n" n
5764 | Int n -> pr " int %s;\n" n
5765 | Int64 n -> pr " hyper %s;\n" n
5767 pr " opaque %s<>;\n" n
5768 | FileIn _ | FileOut _ -> ()
5772 (match fst style with
5775 pr "struct %s_ret {\n" name;
5779 pr "struct %s_ret {\n" name;
5780 pr " hyper %s;\n" n;
5783 pr "struct %s_ret {\n" name;
5786 | RConstString _ | RConstOptString _ ->
5787 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5789 pr "struct %s_ret {\n" name;
5790 pr " string %s<>;\n" n;
5793 pr "struct %s_ret {\n" name;
5794 pr " guestfs_str %s<>;\n" n;
5796 | RStruct (n, typ) ->
5797 pr "struct %s_ret {\n" name;
5798 pr " guestfs_int_%s %s;\n" typ n;
5800 | RStructList (n, typ) ->
5801 pr "struct %s_ret {\n" name;
5802 pr " guestfs_int_%s_list %s;\n" typ n;
5805 pr "struct %s_ret {\n" name;
5806 pr " guestfs_str %s<>;\n" n;
5809 pr "struct %s_ret {\n" name;
5810 pr " opaque %s<>;\n" n;
5815 (* Table of procedure numbers. *)
5816 pr "enum guestfs_procedure {\n";
5818 fun (shortname, _, proc_nr, _, _, _, _) ->
5819 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5821 pr " GUESTFS_PROC_NR_PROCS\n";
5825 (* Having to choose a maximum message size is annoying for several
5826 * reasons (it limits what we can do in the API), but it (a) makes
5827 * the protocol a lot simpler, and (b) provides a bound on the size
5828 * of the daemon which operates in limited memory space.
5830 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5833 (* Message header, etc. *)
5835 /* The communication protocol is now documented in the guestfs(3)
5839 const GUESTFS_PROGRAM = 0x2000F5F5;
5840 const GUESTFS_PROTOCOL_VERSION = 1;
5842 /* These constants must be larger than any possible message length. */
5843 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5844 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5846 enum guestfs_message_direction {
5847 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5848 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5851 enum guestfs_message_status {
5852 GUESTFS_STATUS_OK = 0,
5853 GUESTFS_STATUS_ERROR = 1
5856 const GUESTFS_ERROR_LEN = 256;
5858 struct guestfs_message_error {
5859 string error_message<GUESTFS_ERROR_LEN>;
5862 struct guestfs_message_header {
5863 unsigned prog; /* GUESTFS_PROGRAM */
5864 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5865 guestfs_procedure proc; /* GUESTFS_PROC_x */
5866 guestfs_message_direction direction;
5867 unsigned serial; /* message serial number */
5868 guestfs_message_status status;
5871 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5873 struct guestfs_chunk {
5874 int cancel; /* if non-zero, transfer is cancelled */
5875 /* data size is 0 bytes if the transfer has finished successfully */
5876 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5880 (* Generate the guestfs-structs.h file. *)
5881 and generate_structs_h () =
5882 generate_header CStyle LGPLv2plus;
5884 (* This is a public exported header file containing various
5885 * structures. The structures are carefully written to have
5886 * exactly the same in-memory format as the XDR structures that
5887 * we use on the wire to the daemon. The reason for creating
5888 * copies of these structures here is just so we don't have to
5889 * export the whole of guestfs_protocol.h (which includes much
5890 * unrelated and XDR-dependent stuff that we don't want to be
5891 * public, or required by clients).
5893 * To reiterate, we will pass these structures to and from the
5894 * client with a simple assignment or memcpy, so the format
5895 * must be identical to what rpcgen / the RFC defines.
5898 (* Public structures. *)
5901 pr "struct guestfs_%s {\n" typ;
5904 | name, FChar -> pr " char %s;\n" name
5905 | name, FString -> pr " char *%s;\n" name
5907 pr " uint32_t %s_len;\n" name;
5908 pr " char *%s;\n" name
5909 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5910 | name, FUInt32 -> pr " uint32_t %s;\n" name
5911 | name, FInt32 -> pr " int32_t %s;\n" name
5912 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5913 | name, FInt64 -> pr " int64_t %s;\n" name
5914 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5918 pr "struct guestfs_%s_list {\n" typ;
5919 pr " uint32_t len;\n";
5920 pr " struct guestfs_%s *val;\n" typ;
5923 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5924 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5928 (* Generate the guestfs-actions.h file. *)
5929 and generate_actions_h () =
5930 generate_header CStyle LGPLv2plus;
5932 fun (shortname, style, _, _, _, _, _) ->
5933 let name = "guestfs_" ^ shortname in
5934 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5938 (* Generate the guestfs-internal-actions.h file. *)
5939 and generate_internal_actions_h () =
5940 generate_header CStyle LGPLv2plus;
5942 fun (shortname, style, _, _, _, _, _) ->
5943 let name = "guestfs__" ^ shortname in
5944 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5946 ) non_daemon_functions
5948 (* Generate the client-side dispatch stubs. *)
5949 and generate_client_actions () =
5950 generate_header CStyle LGPLv2plus;
5957 #include <inttypes.h>
5959 #include \"guestfs.h\"
5960 #include \"guestfs-internal.h\"
5961 #include \"guestfs-internal-actions.h\"
5962 #include \"guestfs_protocol.h\"
5964 /* Check the return message from a call for validity. */
5966 check_reply_header (guestfs_h *g,
5967 const struct guestfs_message_header *hdr,
5968 unsigned int proc_nr, unsigned int serial)
5970 if (hdr->prog != GUESTFS_PROGRAM) {
5971 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5974 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5975 error (g, \"wrong protocol version (%%d/%%d)\",
5976 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5979 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5980 error (g, \"unexpected message direction (%%d/%%d)\",
5981 hdr->direction, GUESTFS_DIRECTION_REPLY);
5984 if (hdr->proc != proc_nr) {
5985 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5988 if (hdr->serial != serial) {
5989 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5996 /* Check we are in the right state to run a high-level action. */
5998 check_state (guestfs_h *g, const char *caller)
6000 if (!guestfs__is_ready (g)) {
6001 if (guestfs__is_config (g) || guestfs__is_launching (g))
6002 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6005 error (g, \"%%s called from the wrong state, %%d != READY\",
6006 caller, guestfs__get_state (g));
6014 let error_code_of = function
6015 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6016 | RConstString _ | RConstOptString _
6017 | RString _ | RStringList _
6018 | RStruct _ | RStructList _
6019 | RHashtable _ | RBufferOut _ -> "NULL"
6022 (* Generate code to check String-like parameters are not passed in
6023 * as NULL (returning an error if they are).
6025 let check_null_strings shortname style =
6026 let pr_newline = ref false in
6029 (* parameters which should not be NULL *)
6039 pr " if (%s == NULL) {\n" n;
6040 pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6041 pr " \"%s\", \"%s\");\n" shortname n;
6042 pr " return %s;\n" (error_code_of (fst style));
6049 (* not applicable *)
6055 if !pr_newline then pr "\n";
6058 (* Generate code to generate guestfish call traces. *)
6059 let trace_call shortname style =
6060 pr " if (guestfs__get_trace (g)) {\n";
6063 List.exists (function
6064 | StringList _ | DeviceList _ -> true
6065 | _ -> false) (snd style) in
6071 pr " printf (\"%s\");\n" shortname;
6074 | String n (* strings *)
6081 (* guestfish doesn't support string escaping, so neither do we *)
6082 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
6083 | OptString n -> (* string option *)
6084 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6085 pr " else printf (\" null\");\n"
6087 | DeviceList n -> (* string list *)
6088 pr " putchar (' ');\n";
6089 pr " putchar ('\"');\n";
6090 pr " for (i = 0; %s[i]; ++i) {\n" n;
6091 pr " if (i > 0) putchar (' ');\n";
6092 pr " fputs (%s[i], stdout);\n" n;
6094 pr " putchar ('\"');\n";
6095 | Bool n -> (* boolean *)
6096 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
6097 | Int n -> (* int *)
6098 pr " printf (\" %%d\", %s);\n" n
6100 pr " printf (\" %%\" PRIi64, %s);\n" n
6102 pr " putchar ('\\n');\n";
6107 (* For non-daemon functions, generate a wrapper around each function. *)
6109 fun (shortname, style, _, _, _, _, _) ->
6110 let name = "guestfs_" ^ shortname in
6112 generate_prototype ~extern:false ~semicolon:false ~newline:true
6113 ~handle:"g" name style;
6115 check_null_strings shortname style;
6116 trace_call shortname style;
6117 pr " return guestfs__%s " shortname;
6118 generate_c_call_args ~handle:"g" style;
6122 ) non_daemon_functions;
6124 (* Client-side stubs for each function. *)
6126 fun (shortname, style, _, _, _, _, _) ->
6127 let name = "guestfs_" ^ shortname in
6128 let error_code = error_code_of (fst style) in
6130 (* Generate the action stub. *)
6131 generate_prototype ~extern:false ~semicolon:false ~newline:true
6132 ~handle:"g" name style;
6136 (match snd style with
6138 | _ -> pr " struct %s_args args;\n" name
6141 pr " guestfs_message_header hdr;\n";
6142 pr " guestfs_message_error err;\n";
6144 match fst style with
6146 | RConstString _ | RConstOptString _ ->
6147 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6149 | RBool _ | RString _ | RStringList _
6150 | RStruct _ | RStructList _
6151 | RHashtable _ | RBufferOut _ ->
6152 pr " struct %s_ret ret;\n" name;
6155 pr " int serial;\n";
6158 check_null_strings shortname style;
6159 trace_call shortname style;
6160 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
6161 shortname error_code;
6162 pr " guestfs___set_busy (g);\n";
6165 (* Send the main header and arguments. *)
6166 (match snd style with
6168 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6169 (String.uppercase shortname)
6173 | Pathname n | Device n | Dev_or_Path n | String n ->
6174 pr " args.%s = (char *) %s;\n" n n
6176 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
6177 | StringList n | DeviceList n ->
6178 pr " args.%s.%s_val = (char **) %s;\n" n n n;
6179 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6181 pr " args.%s = %s;\n" n n
6183 pr " args.%s = %s;\n" n n
6185 pr " args.%s = %s;\n" n n
6186 | FileIn _ | FileOut _ -> ()
6188 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6189 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6190 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6192 pr " guestfs___end_busy (g);\n";
6193 pr " return %s;\n" error_code;
6195 pr " args.%s.%s_val = (char *) %s;\n" n n n;
6196 pr " args.%s.%s_len = %s_size;\n" n n n
6198 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6199 (String.uppercase shortname);
6200 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6203 pr " if (serial == -1) {\n";
6204 pr " guestfs___end_busy (g);\n";
6205 pr " return %s;\n" error_code;
6209 (* Send any additional files (FileIn) requested. *)
6210 let need_read_reply_label = ref false in
6214 pr " r = guestfs___send_file (g, %s);\n" n;
6215 pr " if (r == -1) {\n";
6216 pr " guestfs___end_busy (g);\n";
6217 pr " return %s;\n" error_code;
6219 pr " if (r == -2) /* daemon cancelled */\n";
6220 pr " goto read_reply;\n";
6221 need_read_reply_label := true;
6226 (* Wait for the reply from the remote end. *)
6227 if !need_read_reply_label then pr " read_reply:\n";
6228 pr " memset (&hdr, 0, sizeof hdr);\n";
6229 pr " memset (&err, 0, sizeof err);\n";
6230 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
6232 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
6236 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6239 pr " if (r == -1) {\n";
6240 pr " guestfs___end_busy (g);\n";
6241 pr " return %s;\n" error_code;
6245 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6246 (String.uppercase shortname);
6247 pr " guestfs___end_busy (g);\n";
6248 pr " return %s;\n" error_code;
6252 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6253 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6254 pr " free (err.error_message);\n";
6255 pr " guestfs___end_busy (g);\n";
6256 pr " return %s;\n" error_code;
6260 (* Expecting to receive further files (FileOut)? *)
6264 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6265 pr " guestfs___end_busy (g);\n";
6266 pr " return %s;\n" error_code;
6272 pr " guestfs___end_busy (g);\n";
6274 (match fst style with
6275 | RErr -> pr " return 0;\n"
6276 | RInt n | RInt64 n | RBool n ->
6277 pr " return ret.%s;\n" n
6278 | RConstString _ | RConstOptString _ ->
6279 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6281 pr " return ret.%s; /* caller will free */\n" n
6282 | RStringList n | RHashtable n ->
6283 pr " /* caller will free this, but we need to add a NULL entry */\n";
6284 pr " ret.%s.%s_val =\n" n n;
6285 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6286 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6288 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6289 pr " return ret.%s.%s_val;\n" n n
6291 pr " /* caller will free this */\n";
6292 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6293 | RStructList (n, _) ->
6294 pr " /* caller will free this */\n";
6295 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6297 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6298 pr " * _val might be NULL here. To make the API saner for\n";
6299 pr " * callers, we turn this case into a unique pointer (using\n";
6300 pr " * malloc(1)).\n";
6302 pr " if (ret.%s.%s_len > 0) {\n" n n;
6303 pr " *size_r = ret.%s.%s_len;\n" n n;
6304 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6306 pr " free (ret.%s.%s_val);\n" n n;
6307 pr " char *p = safe_malloc (g, 1);\n";
6308 pr " *size_r = ret.%s.%s_len;\n" n n;
6316 (* Functions to free structures. *)
6317 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6318 pr " * structure format is identical to the XDR format. See note in\n";
6319 pr " * generator.ml.\n";
6326 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6328 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6334 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6336 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6343 (* Generate daemon/actions.h. *)
6344 and generate_daemon_actions_h () =
6345 generate_header CStyle GPLv2plus;
6347 pr "#include \"../src/guestfs_protocol.h\"\n";
6351 fun (name, style, _, _, _, _, _) ->
6353 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6357 (* Generate the linker script which controls the visibility of
6358 * symbols in the public ABI and ensures no other symbols get
6359 * exported accidentally.
6361 and generate_linker_script () =
6362 generate_header HashStyle GPLv2plus;
6367 "guestfs_get_error_handler";
6368 "guestfs_get_out_of_memory_handler";
6369 "guestfs_last_error";
6370 "guestfs_set_close_callback";
6371 "guestfs_set_error_handler";
6372 "guestfs_set_launch_done_callback";
6373 "guestfs_set_log_message_callback";
6374 "guestfs_set_out_of_memory_handler";
6375 "guestfs_set_subprocess_quit_callback";
6377 (* Unofficial parts of the API: the bindings code use these
6378 * functions, so it is useful to export them.
6380 "guestfs_safe_calloc";
6381 "guestfs_safe_malloc";
6382 "guestfs_safe_strdup";
6383 "guestfs_safe_memdup";
6386 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6390 List.map (fun (typ, _) ->
6391 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6394 let globals = List.sort compare (globals @ functions @ structs) in
6398 List.iter (pr " %s;\n") globals;
6405 (* Generate the server-side stubs. *)
6406 and generate_daemon_actions () =
6407 generate_header CStyle GPLv2plus;
6409 pr "#include <config.h>\n";
6411 pr "#include <stdio.h>\n";
6412 pr "#include <stdlib.h>\n";
6413 pr "#include <string.h>\n";
6414 pr "#include <inttypes.h>\n";
6415 pr "#include <rpc/types.h>\n";
6416 pr "#include <rpc/xdr.h>\n";
6418 pr "#include \"daemon.h\"\n";
6419 pr "#include \"c-ctype.h\"\n";
6420 pr "#include \"../src/guestfs_protocol.h\"\n";
6421 pr "#include \"actions.h\"\n";
6425 fun (name, style, _, _, _, _, _) ->
6426 (* Generate server-side stubs. *)
6427 pr "static void %s_stub (XDR *xdr_in)\n" name;
6430 match fst style with
6431 | RErr | RInt _ -> pr " int r;\n"; "-1"
6432 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6433 | RBool _ -> pr " int r;\n"; "-1"
6434 | RConstString _ | RConstOptString _ ->
6435 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6436 | RString _ -> pr " char *r;\n"; "NULL"
6437 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6438 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6439 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6441 pr " size_t size = 1;\n";
6445 (match snd style with
6448 pr " struct guestfs_%s_args args;\n" name;
6451 | Device n | Dev_or_Path n
6454 | OptString n -> pr " char *%s;\n" n
6455 | StringList n | DeviceList n -> pr " char **%s;\n" n
6456 | Bool n -> pr " int %s;\n" n
6457 | Int n -> pr " int %s;\n" n
6458 | Int64 n -> pr " int64_t %s;\n" n
6459 | FileIn _ | FileOut _ -> ()
6461 pr " const char *%s;\n" n;
6462 pr " size_t %s_size;\n" n
6468 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6470 (match snd style with
6473 pr " memset (&args, 0, sizeof args);\n";
6475 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6477 pr " if (cancel_receive () != -2)\n";
6478 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6482 pr " char *%s = args.%s;\n" n n
6484 let pr_list_handling_code n =
6485 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6486 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6487 pr " if (%s == NULL) {\n" n;
6489 pr " if (cancel_receive () != -2)\n";
6490 pr " reply_with_perror (\"realloc\");\n";
6493 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6494 pr " args.%s.%s_val = %s;\n" n n n;
6500 pr " ABS_PATH (%s, %s, goto done);\n"
6501 n (if is_filein then "cancel_receive ()" else "0");
6504 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6505 n (if is_filein then "cancel_receive ()" else "0");
6508 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6509 n (if is_filein then "cancel_receive ()" else "0");
6510 | String n -> pr_args n
6511 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6513 pr_list_handling_code n;
6515 pr_list_handling_code n;
6516 pr " /* Ensure that each is a device,\n";
6517 pr " * and perform device name translation.\n";
6521 pr " for (i = 0; %s[i] != NULL; ++i)\n" n;
6522 pr " RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6523 (if is_filein then "cancel_receive ()" else "0");
6525 | Bool n -> pr " %s = args.%s;\n" n n
6526 | Int n -> pr " %s = args.%s;\n" n n
6527 | Int64 n -> pr " %s = args.%s;\n" n n
6528 | FileIn _ | FileOut _ -> ()
6530 pr " %s = args.%s.%s_val;\n" n n n;
6531 pr " %s_size = args.%s.%s_len;\n" n n n
6536 (* this is used at least for do_equal *)
6537 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6538 (* Emit NEED_ROOT just once, even when there are two or
6539 more Pathname args *)
6540 pr " NEED_ROOT (%s, goto done);\n"
6541 (if is_filein then "cancel_receive ()" else "0");
6544 (* Don't want to call the impl with any FileIn or FileOut
6545 * parameters, since these go "outside" the RPC protocol.
6548 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6550 pr " r = do_%s " name;
6551 generate_c_call_args (fst style, args');
6554 (match fst style with
6555 | RErr | RInt _ | RInt64 _ | RBool _
6556 | RConstString _ | RConstOptString _
6557 | RString _ | RStringList _ | RHashtable _
6558 | RStruct (_, _) | RStructList (_, _) ->
6559 pr " if (r == %s)\n" error_code;
6560 pr " /* do_%s has already called reply_with_error */\n" name;
6564 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6565 pr " * an ordinary zero-length buffer), so be careful ...\n";
6567 pr " if (size == 1 && r == %s)\n" error_code;
6568 pr " /* do_%s has already called reply_with_error */\n" name;
6573 (* If there are any FileOut parameters, then the impl must
6574 * send its own reply.
6577 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6579 pr " /* do_%s has already sent a reply */\n" name
6581 match fst style with
6582 | RErr -> pr " reply (NULL, NULL);\n"
6583 | RInt n | RInt64 n | RBool n ->
6584 pr " struct guestfs_%s_ret ret;\n" name;
6585 pr " ret.%s = r;\n" n;
6586 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6588 | RConstString _ | RConstOptString _ ->
6589 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6591 pr " struct guestfs_%s_ret ret;\n" name;
6592 pr " ret.%s = r;\n" n;
6593 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6596 | RStringList n | RHashtable n ->
6597 pr " struct guestfs_%s_ret ret;\n" name;
6598 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6599 pr " ret.%s.%s_val = r;\n" n n;
6600 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6602 pr " free_strings (r);\n"
6604 pr " struct guestfs_%s_ret ret;\n" name;
6605 pr " ret.%s = *r;\n" n;
6606 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6608 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6610 | RStructList (n, _) ->
6611 pr " struct guestfs_%s_ret ret;\n" name;
6612 pr " ret.%s = *r;\n" n;
6613 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6615 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6618 pr " struct guestfs_%s_ret ret;\n" name;
6619 pr " ret.%s.%s_val = r;\n" n n;
6620 pr " ret.%s.%s_len = size;\n" n n;
6621 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6626 (* Free the args. *)
6628 (match snd style with
6631 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6638 (* Dispatch function. *)
6639 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6641 pr " switch (proc_nr) {\n";
6644 fun (name, style, _, _, _, _, _) ->
6645 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6646 pr " %s_stub (xdr_in);\n" name;
6651 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";
6656 (* LVM columns and tokenization functions. *)
6657 (* XXX This generates crap code. We should rethink how we
6663 pr "static const char *lvm_%s_cols = \"%s\";\n"
6664 typ (String.concat "," (List.map fst cols));
6667 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6669 pr " char *tok, *p, *next;\n";
6670 pr " size_t i, j;\n";
6673 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6676 pr " if (!str) {\n";
6677 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6680 pr " if (!*str || c_isspace (*str)) {\n";
6681 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6686 fun (name, coltype) ->
6687 pr " if (!tok) {\n";
6688 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6691 pr " p = strchrnul (tok, ',');\n";
6692 pr " if (*p) next = p+1; else next = NULL;\n";
6693 pr " *p = '\\0';\n";
6696 pr " r->%s = strdup (tok);\n" name;
6697 pr " if (r->%s == NULL) {\n" name;
6698 pr " perror (\"strdup\");\n";
6702 pr " for (i = j = 0; i < 32; ++j) {\n";
6703 pr " if (tok[j] == '\\0') {\n";
6704 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6706 pr " } else if (tok[j] != '-')\n";
6707 pr " r->%s[i++] = tok[j];\n" name;
6710 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6711 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6715 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6716 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6720 pr " if (tok[0] == '\\0')\n";
6721 pr " r->%s = -1;\n" name;
6722 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6723 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6726 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6727 assert false (* can never be an LVM column *)
6729 pr " tok = next;\n";
6732 pr " if (tok != NULL) {\n";
6733 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6740 pr "guestfs_int_lvm_%s_list *\n" typ;
6741 pr "parse_command_line_%ss (void)\n" typ;
6743 pr " char *out, *err;\n";
6744 pr " char *p, *pend;\n";
6746 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6747 pr " void *newp;\n";
6749 pr " ret = malloc (sizeof *ret);\n";
6750 pr " if (!ret) {\n";
6751 pr " reply_with_perror (\"malloc\");\n";
6752 pr " return NULL;\n";
6755 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6756 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6758 pr " r = command (&out, &err,\n";
6759 pr " \"lvm\", \"%ss\",\n" typ;
6760 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6761 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6762 pr " if (r == -1) {\n";
6763 pr " reply_with_error (\"%%s\", err);\n";
6764 pr " free (out);\n";
6765 pr " free (err);\n";
6766 pr " free (ret);\n";
6767 pr " return NULL;\n";
6770 pr " free (err);\n";
6772 pr " /* Tokenize each line of the output. */\n";
6775 pr " while (p) {\n";
6776 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6777 pr " if (pend) {\n";
6778 pr " *pend = '\\0';\n";
6782 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6785 pr " if (!*p) { /* Empty line? Skip it. */\n";
6790 pr " /* Allocate some space to store this next entry. */\n";
6791 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6792 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6793 pr " if (newp == NULL) {\n";
6794 pr " reply_with_perror (\"realloc\");\n";
6795 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6796 pr " free (ret);\n";
6797 pr " free (out);\n";
6798 pr " return NULL;\n";
6800 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6802 pr " /* Tokenize the next entry. */\n";
6803 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6804 pr " if (r == -1) {\n";
6805 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6806 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6807 pr " free (ret);\n";
6808 pr " free (out);\n";
6809 pr " return NULL;\n";
6816 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6818 pr " free (out);\n";
6819 pr " return ret;\n";
6822 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6824 (* Generate a list of function names, for debugging in the daemon.. *)
6825 and generate_daemon_names () =
6826 generate_header CStyle GPLv2plus;
6828 pr "#include <config.h>\n";
6830 pr "#include \"daemon.h\"\n";
6833 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6834 pr "const char *function_names[] = {\n";
6836 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6840 (* Generate the optional groups for the daemon to implement
6841 * guestfs_available.
6843 and generate_daemon_optgroups_c () =
6844 generate_header CStyle GPLv2plus;
6846 pr "#include <config.h>\n";
6848 pr "#include \"daemon.h\"\n";
6849 pr "#include \"optgroups.h\"\n";
6852 pr "struct optgroup optgroups[] = {\n";
6855 pr " { \"%s\", optgroup_%s_available },\n" group group
6857 pr " { NULL, NULL }\n";
6860 and generate_daemon_optgroups_h () =
6861 generate_header CStyle GPLv2plus;
6865 pr "extern int optgroup_%s_available (void);\n" group
6868 (* Generate the tests. *)
6869 and generate_tests () =
6870 generate_header CStyle GPLv2plus;
6877 #include <sys/types.h>
6880 #include \"guestfs.h\"
6881 #include \"guestfs-internal.h\"
6883 static guestfs_h *g;
6884 static int suppress_error = 0;
6886 static void print_error (guestfs_h *g, void *data, const char *msg)
6888 if (!suppress_error)
6889 fprintf (stderr, \"%%s\\n\", msg);
6892 /* FIXME: nearly identical code appears in fish.c */
6893 static void print_strings (char *const *argv)
6897 for (argc = 0; argv[argc] != NULL; ++argc)
6898 printf (\"\\t%%s\\n\", argv[argc]);
6902 static void print_table (char const *const *argv)
6906 for (i = 0; argv[i] != NULL; i += 2)
6907 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6912 is_available (const char *group)
6914 const char *groups[] = { group, NULL };
6918 r = guestfs_available (g, (char **) groups);
6925 incr (guestfs_h *g, void *iv)
6927 int *i = (int *) iv;
6933 (* Generate a list of commands which are not tested anywhere. *)
6934 pr "static void no_test_warnings (void)\n";
6937 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6939 fun (_, _, _, _, tests, _, _) ->
6940 let tests = filter_map (
6942 | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6943 | (_, Disabled, _) -> None
6945 let seq = List.concat (List.map seq_of_test tests) in
6946 let cmds_tested = List.map List.hd seq in
6947 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6951 fun (name, _, _, _, _, _, _) ->
6952 if not (Hashtbl.mem hash name) then
6953 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6959 (* Generate the actual tests. Note that we generate the tests
6960 * in reverse order, deliberately, so that (in general) the
6961 * newest tests run first. This makes it quicker and easier to
6966 fun (name, _, _, flags, tests, _, _) ->
6967 mapi (generate_one_test name flags) tests
6968 ) (List.rev all_functions) in
6969 let test_names = List.concat test_names in
6970 let nr_tests = List.length test_names in
6973 int main (int argc, char *argv[])
6976 unsigned long int n_failed = 0;
6977 const char *filename;
6979 int nr_tests, test_num = 0;
6981 setbuf (stdout, NULL);
6983 no_test_warnings ();
6985 g = guestfs_create ();
6987 printf (\"guestfs_create FAILED\\n\");
6988 exit (EXIT_FAILURE);
6991 guestfs_set_error_handler (g, print_error, NULL);
6993 guestfs_set_path (g, \"../appliance\");
6995 filename = \"test1.img\";
6996 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6999 exit (EXIT_FAILURE);
7001 if (lseek (fd, %d, SEEK_SET) == -1) {
7005 exit (EXIT_FAILURE);
7007 if (write (fd, &c, 1) == -1) {
7011 exit (EXIT_FAILURE);
7013 if (close (fd) == -1) {
7016 exit (EXIT_FAILURE);
7018 if (guestfs_add_drive (g, filename) == -1) {
7019 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7020 exit (EXIT_FAILURE);
7023 filename = \"test2.img\";
7024 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7027 exit (EXIT_FAILURE);
7029 if (lseek (fd, %d, SEEK_SET) == -1) {
7033 exit (EXIT_FAILURE);
7035 if (write (fd, &c, 1) == -1) {
7039 exit (EXIT_FAILURE);
7041 if (close (fd) == -1) {
7044 exit (EXIT_FAILURE);
7046 if (guestfs_add_drive (g, filename) == -1) {
7047 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7048 exit (EXIT_FAILURE);
7051 filename = \"test3.img\";
7052 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7055 exit (EXIT_FAILURE);
7057 if (lseek (fd, %d, SEEK_SET) == -1) {
7061 exit (EXIT_FAILURE);
7063 if (write (fd, &c, 1) == -1) {
7067 exit (EXIT_FAILURE);
7069 if (close (fd) == -1) {
7072 exit (EXIT_FAILURE);
7074 if (guestfs_add_drive (g, filename) == -1) {
7075 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7076 exit (EXIT_FAILURE);
7079 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7080 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7081 exit (EXIT_FAILURE);
7084 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7087 if (guestfs_launch (g) == -1) {
7088 printf (\"guestfs_launch FAILED\\n\");
7089 exit (EXIT_FAILURE);
7092 /* Cancel previous alarm. */
7097 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7101 pr " test_num++;\n";
7102 pr " if (guestfs_get_verbose (g))\n";
7103 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
7104 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7105 pr " if (%s () == -1) {\n" test_name;
7106 pr " printf (\"%s FAILED\\n\");\n" test_name;
7107 pr " n_failed++;\n";
7112 pr " /* Check close callback is called. */
7113 int close_sentinel = 1;
7114 guestfs_set_close_callback (g, incr, &close_sentinel);
7118 if (close_sentinel != 2) {
7119 fprintf (stderr, \"close callback was not called\\n\");
7120 exit (EXIT_FAILURE);
7123 unlink (\"test1.img\");
7124 unlink (\"test2.img\");
7125 unlink (\"test3.img\");
7129 pr " if (n_failed > 0) {\n";
7130 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7131 pr " exit (EXIT_FAILURE);\n";
7135 pr " exit (EXIT_SUCCESS);\n";
7138 and generate_one_test name flags i (init, prereq, test) =
7139 let test_name = sprintf "test_%s_%d" name i in
7142 static int %s_skip (void)
7146 str = getenv (\"TEST_ONLY\");
7148 return strstr (str, \"%s\") == NULL;
7149 str = getenv (\"SKIP_%s\");
7150 if (str && STREQ (str, \"1\")) return 1;
7151 str = getenv (\"SKIP_TEST_%s\");
7152 if (str && STREQ (str, \"1\")) return 1;
7156 " test_name name (String.uppercase test_name) (String.uppercase name);
7159 | Disabled | Always | IfAvailable _ -> ()
7160 | If code | Unless code ->
7161 pr "static int %s_prereq (void)\n" test_name;
7169 static int %s (void)
7172 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
7176 " test_name test_name test_name;
7178 (* Optional functions should only be tested if the relevant
7179 * support is available in the daemon.
7184 pr " if (!is_available (\"%s\")) {\n" group;
7185 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7193 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7195 pr " if (! %s_prereq ()) {\n" test_name;
7196 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7200 generate_one_test_body name i test_name init test;
7202 pr " if (%s_prereq ()) {\n" test_name;
7203 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7207 generate_one_test_body name i test_name init test;
7208 | IfAvailable group ->
7209 pr " if (!is_available (\"%s\")) {\n" group;
7210 pr " printf (\" %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7214 generate_one_test_body name i test_name init test;
7216 generate_one_test_body name i test_name init test
7224 and generate_one_test_body name i test_name init test =
7226 | InitNone (* XXX at some point, InitNone and InitEmpty became
7227 * folded together as the same thing. Really we should
7228 * make InitNone do nothing at all, but the tests may
7229 * need to be checked to make sure this is OK.
7232 pr " /* InitNone|InitEmpty for %s */\n" test_name;
7233 List.iter (generate_test_command_call test_name)
7234 [["blockdev_setrw"; "/dev/sda"];
7238 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7239 List.iter (generate_test_command_call test_name)
7240 [["blockdev_setrw"; "/dev/sda"];
7243 ["part_disk"; "/dev/sda"; "mbr"]]
7245 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7246 List.iter (generate_test_command_call test_name)
7247 [["blockdev_setrw"; "/dev/sda"];
7250 ["part_disk"; "/dev/sda"; "mbr"];
7251 ["mkfs"; "ext2"; "/dev/sda1"];
7252 ["mount_options"; ""; "/dev/sda1"; "/"]]
7253 | InitBasicFSonLVM ->
7254 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7256 List.iter (generate_test_command_call test_name)
7257 [["blockdev_setrw"; "/dev/sda"];
7260 ["part_disk"; "/dev/sda"; "mbr"];
7261 ["pvcreate"; "/dev/sda1"];
7262 ["vgcreate"; "VG"; "/dev/sda1"];
7263 ["lvcreate"; "LV"; "VG"; "8"];
7264 ["mkfs"; "ext2"; "/dev/VG/LV"];
7265 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7267 pr " /* InitISOFS for %s */\n" test_name;
7268 List.iter (generate_test_command_call test_name)
7269 [["blockdev_setrw"; "/dev/sda"];
7272 ["mount_ro"; "/dev/sdd"; "/"]]
7275 let get_seq_last = function
7277 failwithf "%s: you cannot use [] (empty list) when expecting a command"
7280 let seq = List.rev seq in
7281 List.rev (List.tl seq), List.hd seq
7286 pr " /* TestRun for %s (%d) */\n" name i;
7287 List.iter (generate_test_command_call test_name) seq
7288 | TestOutput (seq, expected) ->
7289 pr " /* TestOutput for %s (%d) */\n" name i;
7290 pr " const char *expected = \"%s\";\n" (c_quote expected);
7291 let seq, last = get_seq_last seq in
7293 pr " if (STRNEQ (r, expected)) {\n";
7294 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7298 List.iter (generate_test_command_call test_name) seq;
7299 generate_test_command_call ~test test_name last
7300 | TestOutputList (seq, expected) ->
7301 pr " /* TestOutputList for %s (%d) */\n" name i;
7302 let seq, last = get_seq_last seq in
7306 pr " if (!r[%d]) {\n" i;
7307 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7308 pr " print_strings (r);\n";
7312 pr " const char *expected = \"%s\";\n" (c_quote str);
7313 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7314 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7319 pr " if (r[%d] != NULL) {\n" (List.length expected);
7320 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7322 pr " print_strings (r);\n";
7326 List.iter (generate_test_command_call test_name) seq;
7327 generate_test_command_call ~test test_name last
7328 | TestOutputListOfDevices (seq, expected) ->
7329 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7330 let seq, last = get_seq_last seq in
7334 pr " if (!r[%d]) {\n" i;
7335 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7336 pr " print_strings (r);\n";
7340 pr " const char *expected = \"%s\";\n" (c_quote str);
7341 pr " r[%d][5] = 's';\n" i;
7342 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7343 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7348 pr " if (r[%d] != NULL) {\n" (List.length expected);
7349 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7351 pr " print_strings (r);\n";
7355 List.iter (generate_test_command_call test_name) seq;
7356 generate_test_command_call ~test test_name last
7357 | TestOutputInt (seq, expected) ->
7358 pr " /* TestOutputInt for %s (%d) */\n" name i;
7359 let seq, last = get_seq_last seq in
7361 pr " if (r != %d) {\n" expected;
7362 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7368 List.iter (generate_test_command_call test_name) seq;
7369 generate_test_command_call ~test test_name last
7370 | TestOutputIntOp (seq, op, expected) ->
7371 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7372 let seq, last = get_seq_last seq in
7374 pr " if (! (r %s %d)) {\n" op expected;
7375 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7376 test_name op expected;
7381 List.iter (generate_test_command_call test_name) seq;
7382 generate_test_command_call ~test test_name last
7383 | TestOutputTrue seq ->
7384 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7385 let seq, last = get_seq_last seq in
7388 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7393 List.iter (generate_test_command_call test_name) seq;
7394 generate_test_command_call ~test test_name last
7395 | TestOutputFalse seq ->
7396 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7397 let seq, last = get_seq_last seq in
7400 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7405 List.iter (generate_test_command_call test_name) seq;
7406 generate_test_command_call ~test test_name last
7407 | TestOutputLength (seq, expected) ->
7408 pr " /* TestOutputLength for %s (%d) */\n" name i;
7409 let seq, last = get_seq_last seq in
7412 pr " for (j = 0; j < %d; ++j)\n" expected;
7413 pr " if (r[j] == NULL) {\n";
7414 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7416 pr " print_strings (r);\n";
7419 pr " if (r[j] != NULL) {\n";
7420 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7422 pr " print_strings (r);\n";
7426 List.iter (generate_test_command_call test_name) seq;
7427 generate_test_command_call ~test test_name last
7428 | TestOutputBuffer (seq, expected) ->
7429 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7430 pr " const char *expected = \"%s\";\n" (c_quote expected);
7431 let seq, last = get_seq_last seq in
7432 let len = String.length expected in
7434 pr " if (size != %d) {\n" len;
7435 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7438 pr " if (STRNEQLEN (r, expected, size)) {\n";
7439 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7443 List.iter (generate_test_command_call test_name) seq;
7444 generate_test_command_call ~test test_name last
7445 | TestOutputStruct (seq, checks) ->
7446 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7447 let seq, last = get_seq_last seq in
7451 | CompareWithInt (field, expected) ->
7452 pr " if (r->%s != %d) {\n" field expected;
7453 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7454 test_name field expected;
7455 pr " (int) r->%s);\n" field;
7458 | CompareWithIntOp (field, op, expected) ->
7459 pr " if (!(r->%s %s %d)) {\n" field op expected;
7460 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7461 test_name field op expected;
7462 pr " (int) r->%s);\n" field;
7465 | CompareWithString (field, expected) ->
7466 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7467 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7468 test_name field expected;
7469 pr " r->%s);\n" field;
7472 | CompareFieldsIntEq (field1, field2) ->
7473 pr " if (r->%s != r->%s) {\n" field1 field2;
7474 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7475 test_name field1 field2;
7476 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7479 | CompareFieldsStrEq (field1, field2) ->
7480 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7481 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7482 test_name field1 field2;
7483 pr " r->%s, r->%s);\n" field1 field2;
7488 List.iter (generate_test_command_call test_name) seq;
7489 generate_test_command_call ~test test_name last
7490 | TestLastFail seq ->
7491 pr " /* TestLastFail for %s (%d) */\n" name i;
7492 let seq, last = get_seq_last seq in
7493 List.iter (generate_test_command_call test_name) seq;
7494 generate_test_command_call test_name ~expect_error:true last
7496 (* Generate the code to run a command, leaving the result in 'r'.
7497 * If you expect to get an error then you should set expect_error:true.
7499 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7501 | [] -> assert false
7503 (* Look up the command to find out what args/ret it has. *)
7506 let _, style, _, _, _, _, _ =
7507 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7510 failwithf "%s: in test, command %s was not found" test_name name in
7512 if List.length (snd style) <> List.length args then
7513 failwithf "%s: in test, wrong number of args given to %s"
7520 | OptString n, "NULL" -> ()
7523 | Dev_or_Path n, arg
7525 | OptString n, arg ->
7526 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7527 | BufferIn n, arg ->
7528 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7529 pr " size_t %s_size = %d;\n" n (String.length arg)
7533 | FileIn _, _ | FileOut _, _ -> ()
7534 | StringList n, "" | DeviceList n, "" ->
7535 pr " const char *const %s[1] = { NULL };\n" n
7536 | StringList n, arg | DeviceList n, arg ->
7537 let strs = string_split " " arg in
7540 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7542 pr " const char *const %s[] = {\n" n;
7544 fun i _ -> pr " %s_%d,\n" n i
7548 ) (List.combine (snd style) args);
7551 match fst style with
7552 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7553 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7554 | RConstString _ | RConstOptString _ ->
7555 pr " const char *r;\n"; "NULL"
7556 | RString _ -> pr " char *r;\n"; "NULL"
7557 | RStringList _ | RHashtable _ ->
7561 | RStruct (_, typ) ->
7562 pr " struct guestfs_%s *r;\n" typ; "NULL"
7563 | RStructList (_, typ) ->
7564 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7567 pr " size_t size;\n";
7570 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7571 pr " r = guestfs_%s (g" name;
7573 (* Generate the parameters. *)
7576 | OptString _, "NULL" -> pr ", NULL"
7578 | Device n, _ | Dev_or_Path n, _
7583 pr ", %s, %s_size" n n
7584 | FileIn _, arg | FileOut _, arg ->
7585 pr ", \"%s\"" (c_quote arg)
7586 | StringList n, _ | DeviceList n, _ ->
7587 pr ", (char **) %s" n
7590 try int_of_string arg
7591 with Failure "int_of_string" ->
7592 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7596 try Int64.of_string arg
7597 with Failure "int_of_string" ->
7598 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7601 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7602 ) (List.combine (snd style) args);
7604 (match fst style with
7605 | RBufferOut _ -> pr ", &size"
7611 if not expect_error then
7612 pr " if (r == %s)\n" error_code
7614 pr " if (r != %s)\n" error_code;
7617 (* Insert the test code. *)
7623 (match fst style with
7624 | RErr | RInt _ | RInt64 _ | RBool _
7625 | RConstString _ | RConstOptString _ -> ()
7626 | RString _ | RBufferOut _ -> pr " free (r);\n"
7627 | RStringList _ | RHashtable _ ->
7628 pr " for (i = 0; r[i] != NULL; ++i)\n";
7629 pr " free (r[i]);\n";
7631 | RStruct (_, typ) ->
7632 pr " guestfs_free_%s (r);\n" typ
7633 | RStructList (_, typ) ->
7634 pr " guestfs_free_%s_list (r);\n" typ
7640 let str = replace_str str "\r" "\\r" in
7641 let str = replace_str str "\n" "\\n" in
7642 let str = replace_str str "\t" "\\t" in
7643 let str = replace_str str "\000" "\\0" in
7646 (* Generate a lot of different functions for guestfish. *)
7647 and generate_fish_cmds () =
7648 generate_header CStyle GPLv2plus;
7652 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7654 let all_functions_sorted =
7656 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7657 ) all_functions_sorted in
7659 pr "#include <config.h>\n";
7661 pr "#include <stdio.h>\n";
7662 pr "#include <stdlib.h>\n";
7663 pr "#include <string.h>\n";
7664 pr "#include <inttypes.h>\n";
7666 pr "#include <guestfs.h>\n";
7667 pr "#include \"c-ctype.h\"\n";
7668 pr "#include \"full-write.h\"\n";
7669 pr "#include \"xstrtol.h\"\n";
7670 pr "#include \"fish.h\"\n";
7672 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
7673 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7676 (* list_commands function, which implements guestfish -h *)
7677 pr "void list_commands (void)\n";
7679 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7680 pr " list_builtin_commands ();\n";
7682 fun (name, _, _, flags, _, shortdesc, _) ->
7683 let name = replace_char name '_' '-' in
7684 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7686 ) all_functions_sorted;
7687 pr " printf (\" %%s\\n\",";
7688 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7692 (* display_command function, which implements guestfish -h cmd *)
7693 pr "int display_command (const char *cmd)\n";
7696 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7697 let name2 = replace_char name '_' '-' in
7699 try find_map (function FishAlias n -> Some n | _ -> None) flags
7700 with Not_found -> name in
7701 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7703 match snd style with
7707 name2 (String.concat " " (List.map name_of_argt args)) in
7710 if List.mem ProtocolLimitWarning flags then
7711 ("\n\n" ^ protocol_limit_warning)
7714 (* For DangerWillRobinson commands, we should probably have
7715 * guestfish prompt before allowing you to use them (especially
7716 * in interactive mode). XXX
7720 if List.mem DangerWillRobinson flags then
7721 ("\n\n" ^ danger_will_robinson)
7726 match deprecation_notice flags with
7728 | Some txt -> "\n\n" ^ txt in
7730 let describe_alias =
7731 if name <> alias then
7732 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7736 pr "STRCASEEQ (cmd, \"%s\")" name;
7737 if name <> name2 then
7738 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7739 if name <> alias then
7740 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7742 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7744 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7745 "=head1 DESCRIPTION\n\n" ^
7746 longdesc ^ warnings ^ describe_alias);
7751 pr " return display_builtin_command (cmd);\n";
7755 let emit_print_list_function typ =
7756 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7759 pr " unsigned int i;\n";
7761 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7762 pr " printf (\"[%%d] = {\\n\", i);\n";
7763 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7764 pr " printf (\"}\\n\");\n";
7770 (* print_* functions *)
7774 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7776 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7779 pr " unsigned int i;\n";
7785 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7787 pr " printf (\"%%s%s: \", indent);\n" name;
7788 pr " for (i = 0; i < 32; ++i)\n";
7789 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7790 pr " printf (\"\\n\");\n"
7792 pr " printf (\"%%s%s: \", indent);\n" name;
7793 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7794 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7795 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7797 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7798 pr " printf (\"\\n\");\n"
7799 | name, (FUInt64|FBytes) ->
7800 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7803 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7806 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7809 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7812 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7814 | name, FOptPercent ->
7815 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7816 typ name name typ name;
7817 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7823 (* Emit a print_TYPE_list function definition only if that function is used. *)
7826 | typ, (RStructListOnly | RStructAndList) ->
7827 (* generate the function for typ *)
7828 emit_print_list_function typ
7829 | typ, _ -> () (* empty *)
7830 ) (rstructs_used_by all_functions);
7832 (* Emit a print_TYPE function definition only if that function is used. *)
7835 | typ, (RStructOnly | RStructAndList) ->
7836 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7838 pr " print_%s_indent (%s, \"\");\n" typ typ;
7841 | typ, _ -> () (* empty *)
7842 ) (rstructs_used_by all_functions);
7844 (* run_<action> actions *)
7846 fun (name, style, _, flags, _, _, _) ->
7847 pr "static int run_%s (const char *cmd, size_t argc, char *argv[])\n" name;
7849 (match fst style with
7852 | RBool _ -> pr " int r;\n"
7853 | RInt64 _ -> pr " int64_t r;\n"
7854 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7855 | RString _ -> pr " char *r;\n"
7856 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7857 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7858 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7861 pr " size_t size;\n";
7867 | OptString n -> pr " const char *%s;\n" n
7871 | FileOut n -> pr " char *%s;\n" n
7873 pr " const char *%s;\n" n;
7874 pr " size_t %s_size;\n" n
7875 | StringList n | DeviceList n -> pr " char **%s;\n" n
7876 | Bool n -> pr " int %s;\n" n
7877 | Int n -> pr " int %s;\n" n
7878 | Int64 n -> pr " int64_t %s;\n" n
7881 (* Check and convert parameters. *)
7882 let argc_expected = List.length (snd style) in
7883 pr " if (argc != %d) {\n" argc_expected;
7884 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7886 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7890 let parse_integer fn fntyp rtyp range name i =
7892 pr " strtol_error xerr;\n";
7893 pr " %s r;\n" fntyp;
7895 pr " xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7896 pr " if (xerr != LONGINT_OK) {\n";
7897 pr " fprintf (stderr,\n";
7898 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7899 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7904 | Some (min, max, comment) ->
7905 pr " /* %s */\n" comment;
7906 pr " if (r < %s || r > %s) {\n" min max;
7907 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7911 pr " /* The check above should ensure this assignment does not overflow. */\n";
7913 pr " %s = r;\n" name;
7922 pr " %s = argv[%d];\n" name i
7924 | Dev_or_Path name ->
7925 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7926 pr " if (%s == NULL) return -1;\n" name
7928 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7931 pr " %s = argv[%d];\n" name i;
7932 pr " %s_size = strlen (argv[%d]);\n" name i
7934 pr " %s = file_in (argv[%d]);\n" name i;
7935 pr " if (%s == NULL) return -1;\n" name
7937 pr " %s = file_out (argv[%d]);\n" name i;
7938 pr " if (%s == NULL) return -1;\n" name
7939 | StringList name | DeviceList name ->
7940 pr " %s = parse_string_list (argv[%d]);\n" name i;
7941 pr " if (%s == NULL) return -1;\n" name;
7943 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7946 let min = "(-(2LL<<30))"
7947 and max = "((2LL<<30)-1)"
7949 "The Int type in the generator is a signed 31 bit int." in
7950 Some (min, max, comment) in
7951 parse_integer "xstrtoll" "long long" "int" range name i
7953 parse_integer "xstrtoll" "long long" "int64_t" None name i
7956 (* Call C API function. *)
7957 pr " r = guestfs_%s " name;
7958 generate_c_call_args ~handle:"g" style;
7963 | Device _ | String _
7964 | OptString _ | Bool _
7967 | Pathname name | Dev_or_Path name | FileOut name ->
7968 pr " free (%s);\n" name
7970 pr " free_file_in (%s);\n" name
7971 | StringList name | DeviceList name ->
7972 pr " free_strings (%s);\n" name
7975 (* Any output flags? *)
7977 let flags = filter_map (
7978 function FishOutput flag -> Some flag | _ -> None
7984 failwithf "%s: more than one FishOutput flag is not allowed" name in
7986 (* Check return value for errors and display command results. *)
7987 (match fst style with
7988 | RErr -> pr " return r;\n"
7990 pr " if (r == -1) return -1;\n";
7991 (match fish_output with
7993 pr " printf (\"%%d\\n\", r);\n";
7994 | Some FishOutputOctal ->
7995 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7996 | Some FishOutputHexadecimal ->
7997 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8000 pr " if (r == -1) return -1;\n";
8001 (match fish_output with
8003 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
8004 | Some FishOutputOctal ->
8005 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8006 | Some FishOutputHexadecimal ->
8007 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8010 pr " if (r == -1) return -1;\n";
8011 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8014 pr " if (r == NULL) return -1;\n";
8015 pr " printf (\"%%s\\n\", r);\n";
8017 | RConstOptString _ ->
8018 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
8021 pr " if (r == NULL) return -1;\n";
8022 pr " printf (\"%%s\\n\", r);\n";
8026 pr " if (r == NULL) return -1;\n";
8027 pr " print_strings (r);\n";
8028 pr " free_strings (r);\n";
8030 | RStruct (_, typ) ->
8031 pr " if (r == NULL) return -1;\n";
8032 pr " print_%s (r);\n" typ;
8033 pr " guestfs_free_%s (r);\n" typ;
8035 | RStructList (_, typ) ->
8036 pr " if (r == NULL) return -1;\n";
8037 pr " print_%s_list (r);\n" typ;
8038 pr " guestfs_free_%s_list (r);\n" typ;
8041 pr " if (r == NULL) return -1;\n";
8042 pr " print_table (r);\n";
8043 pr " free_strings (r);\n";
8046 pr " if (r == NULL) return -1;\n";
8047 pr " if (full_write (1, r, size) != size) {\n";
8048 pr " perror (\"write\");\n";
8059 (* run_action function *)
8060 pr "int run_action (const char *cmd, size_t argc, char *argv[])\n";
8063 fun (name, _, _, flags, _, _, _) ->
8064 let name2 = replace_char name '_' '-' in
8066 try find_map (function FishAlias n -> Some n | _ -> None) flags
8067 with Not_found -> name in
8069 pr "STRCASEEQ (cmd, \"%s\")" name;
8070 if name <> name2 then
8071 pr " || STRCASEEQ (cmd, \"%s\")" name2;
8072 if name <> alias then
8073 pr " || STRCASEEQ (cmd, \"%s\")" alias;
8075 pr " return run_%s (cmd, argc, argv);\n" name;
8079 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8080 pr " if (command_num == 1)\n";
8081 pr " extended_help_message ();\n";
8088 (* Readline completion for guestfish. *)
8089 and generate_fish_completion () =
8090 generate_header CStyle GPLv2plus;
8094 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8104 #ifdef HAVE_LIBREADLINE
8105 #include <readline/readline.h>
8110 #ifdef HAVE_LIBREADLINE
8112 static const char *const commands[] = {
8113 BUILTIN_COMMANDS_FOR_COMPLETION,
8116 (* Get the commands, including the aliases. They don't need to be
8117 * sorted - the generator() function just does a dumb linear search.
8121 fun (name, _, _, flags, _, _, _) ->
8122 let name2 = replace_char name '_' '-' in
8124 try find_map (function FishAlias n -> Some n | _ -> None) flags
8125 with Not_found -> name in
8127 if name <> alias then [name2; alias] else [name2]
8129 let commands = List.flatten commands in
8131 List.iter (pr " \"%s\",\n") commands;
8137 generator (const char *text, int state)
8139 static size_t index, len;
8144 len = strlen (text);
8147 rl_attempted_completion_over = 1;
8149 while ((name = commands[index]) != NULL) {
8151 if (STRCASEEQLEN (name, text, len))
8152 return strdup (name);
8158 #endif /* HAVE_LIBREADLINE */
8160 #ifdef HAVE_RL_COMPLETION_MATCHES
8161 #define RL_COMPLETION_MATCHES rl_completion_matches
8163 #ifdef HAVE_COMPLETION_MATCHES
8164 #define RL_COMPLETION_MATCHES completion_matches
8166 #endif /* else just fail if we don't have either symbol */
8169 do_completion (const char *text, int start, int end)
8171 char **matches = NULL;
8173 #ifdef HAVE_LIBREADLINE
8174 rl_completion_append_character = ' ';
8177 matches = RL_COMPLETION_MATCHES (text, generator);
8178 else if (complete_dest_paths)
8179 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8186 (* Generate the POD documentation for guestfish. *)
8187 and generate_fish_actions_pod () =
8188 let all_functions_sorted =
8190 fun (_, _, _, flags, _, _, _) ->
8191 not (List.mem NotInFish flags || List.mem NotInDocs flags)
8192 ) all_functions_sorted in
8194 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8197 fun (name, style, _, flags, _, _, longdesc) ->
8199 Str.global_substitute rex (
8202 try Str.matched_group 1 s
8204 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8205 "L</" ^ replace_char sub '_' '-' ^ ">"
8207 let name = replace_char name '_' '-' in
8209 try find_map (function FishAlias n -> Some n | _ -> None) flags
8210 with Not_found -> name in
8212 pr "=head2 %s" name;
8213 if name <> alias then
8220 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8221 | OptString n -> pr " %s" n
8222 | StringList n | DeviceList n -> pr " '%s ...'" n
8223 | Bool _ -> pr " true|false"
8224 | Int n -> pr " %s" n
8225 | Int64 n -> pr " %s" n
8226 | FileIn n | FileOut n -> pr " (%s|-)" n
8227 | BufferIn n -> pr " %s" n
8231 pr "%s\n\n" longdesc;
8233 if List.exists (function FileIn _ | FileOut _ -> true
8234 | _ -> false) (snd style) then
8235 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8237 if List.mem ProtocolLimitWarning flags then
8238 pr "%s\n\n" protocol_limit_warning;
8240 if List.mem DangerWillRobinson flags then
8241 pr "%s\n\n" danger_will_robinson;
8243 match deprecation_notice flags with
8245 | Some txt -> pr "%s\n\n" txt
8246 ) all_functions_sorted
8248 and generate_fish_prep_options_h () =
8249 generate_header CStyle GPLv2plus;
8251 pr "#ifndef PREPOPTS_H\n";
8256 const char *name; /* eg. \"fs\" */
8258 size_t nr_params; /* optional parameters */
8259 struct prep_param *params;
8261 const char *shortdesc; /* short description */
8262 const char *longdesc; /* long description */
8264 /* functions to implement it */
8265 void (*prelaunch) (const char *filename, prep_data *);
8266 void (*postlaunch) (const char *filename, prep_data *, const char *device);
8270 const char *pname; /* parameter name */
8271 const char *pdefault; /* parameter default */
8272 const char *pdesc; /* parameter description */
8275 extern const struct prep preps[];
8278 " (List.length prepopts);
8281 fun (name, shortdesc, args, longdesc) ->
8283 extern void prep_prelaunch_%s (const char *filename, prep_data *data);
8284 extern void prep_postlaunch_%s (const char *filename, prep_data *data, const char *device);
8290 pr "#endif /* PREPOPTS_H */\n"
8292 and generate_fish_prep_options_c () =
8293 generate_header CStyle GPLv2plus;
8297 #include \"prepopts.h\"
8302 fun (name, shortdesc, args, longdesc) ->
8303 pr "static struct prep_param %s_args[] = {\n" name;
8305 fun (n, default, desc) ->
8306 pr " { \"%s\", \"%s\", \"%s\" },\n" n default desc
8312 pr "const struct prep preps[] = {\n";
8314 fun (name, shortdesc, args, longdesc) ->
8315 pr " { \"%s\", %d, %s_args,
8318 prep_prelaunch_%s, prep_postlaunch_%s },
8320 name (List.length args) name
8321 (c_quote shortdesc) (c_quote longdesc)
8326 (* Generate a C function prototype. *)
8327 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8328 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8330 ?handle name style =
8331 if extern then pr "extern ";
8332 if static then pr "static ";
8333 (match fst style with
8335 | RInt _ -> pr "int "
8336 | RInt64 _ -> pr "int64_t "
8337 | RBool _ -> pr "int "
8338 | RConstString _ | RConstOptString _ -> pr "const char *"
8339 | RString _ | RBufferOut _ -> pr "char *"
8340 | RStringList _ | RHashtable _ -> pr "char **"
8341 | RStruct (_, typ) ->
8342 if not in_daemon then pr "struct guestfs_%s *" typ
8343 else pr "guestfs_int_%s *" typ
8344 | RStructList (_, typ) ->
8345 if not in_daemon then pr "struct guestfs_%s_list *" typ
8346 else pr "guestfs_int_%s_list *" typ
8348 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8349 pr "%s%s (" prefix name;
8350 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8353 let comma = ref false in
8356 | Some handle -> pr "guestfs_h *%s" handle; comma := true
8360 if single_line then pr ", " else pr ",\n\t\t"
8367 | Device n | Dev_or_Path n
8371 pr "const char *%s" n
8372 | StringList n | DeviceList n ->
8374 pr "char *const *%s" n
8375 | Bool n -> next (); pr "int %s" n
8376 | Int n -> next (); pr "int %s" n
8377 | Int64 n -> next (); pr "int64_t %s" n
8380 if not in_daemon then (next (); pr "const char *%s" n)
8383 pr "const char *%s" n;
8385 pr "size_t %s_size" n
8387 if is_RBufferOut then (next (); pr "size_t *size_r");
8390 if semicolon then pr ";";
8391 if newline then pr "\n"
8393 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8394 and generate_c_call_args ?handle ?(decl = false) style =
8396 let comma = ref false in
8398 if !comma then pr ", ";
8403 | Some handle -> pr "%s" handle; comma := true
8409 pr "%s, %s_size" n n
8412 pr "%s" (name_of_argt arg)
8414 (* For RBufferOut calls, add implicit &size parameter. *)
8416 match fst style with
8424 (* Generate the OCaml bindings interface. *)
8425 and generate_ocaml_mli () =
8426 generate_header OCamlStyle LGPLv2plus;
8429 (** For API documentation you should refer to the C API
8430 in the guestfs(3) manual page. The OCaml API uses almost
8431 exactly the same calls. *)
8434 (** A [guestfs_h] handle. *)
8436 exception Error of string
8437 (** This exception is raised when there is an error. *)
8439 exception Handle_closed of string
8440 (** This exception is raised if you use a {!Guestfs.t} handle
8441 after calling {!close} on it. The string is the name of
8444 val create : unit -> t
8445 (** Create a {!Guestfs.t} handle. *)
8447 val close : t -> unit
8448 (** Close the {!Guestfs.t} handle and free up all resources used
8451 Handles are closed by the garbage collector when they become
8452 unreferenced, but callers can call this in order to provide
8453 predictable cleanup. *)
8456 generate_ocaml_structure_decls ();
8460 fun (name, style, _, _, _, shortdesc, _) ->
8461 generate_ocaml_prototype name style;
8462 pr "(** %s *)\n" shortdesc;
8464 ) all_functions_sorted
8466 (* Generate the OCaml bindings implementation. *)
8467 and generate_ocaml_ml () =
8468 generate_header OCamlStyle LGPLv2plus;
8473 exception Error of string
8474 exception Handle_closed of string
8476 external create : unit -> t = \"ocaml_guestfs_create\"
8477 external close : t -> unit = \"ocaml_guestfs_close\"
8479 (* Give the exceptions names, so they can be raised from the C code. *)
8481 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8482 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8486 generate_ocaml_structure_decls ();
8490 fun (name, style, _, _, _, shortdesc, _) ->
8491 generate_ocaml_prototype ~is_external:true name style;
8492 ) all_functions_sorted
8494 (* Generate the OCaml bindings C implementation. *)
8495 and generate_ocaml_c () =
8496 generate_header CStyle LGPLv2plus;
8503 #include <caml/config.h>
8504 #include <caml/alloc.h>
8505 #include <caml/callback.h>
8506 #include <caml/fail.h>
8507 #include <caml/memory.h>
8508 #include <caml/mlvalues.h>
8509 #include <caml/signals.h>
8511 #include \"guestfs.h\"
8513 #include \"guestfs_c.h\"
8515 /* Copy a hashtable of string pairs into an assoc-list. We return
8516 * the list in reverse order, but hashtables aren't supposed to be
8519 static CAMLprim value
8520 copy_table (char * const * argv)
8523 CAMLlocal5 (rv, pairv, kv, vv, cons);
8527 for (i = 0; argv[i] != NULL; i += 2) {
8528 kv = caml_copy_string (argv[i]);
8529 vv = caml_copy_string (argv[i+1]);
8530 pairv = caml_alloc (2, 0);
8531 Store_field (pairv, 0, kv);
8532 Store_field (pairv, 1, vv);
8533 cons = caml_alloc (2, 0);
8534 Store_field (cons, 1, rv);
8536 Store_field (cons, 0, pairv);
8544 (* Struct copy functions. *)
8546 let emit_ocaml_copy_list_function typ =
8547 pr "static CAMLprim value\n";
8548 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8550 pr " CAMLparam0 ();\n";
8551 pr " CAMLlocal2 (rv, v);\n";
8552 pr " unsigned int i;\n";
8554 pr " if (%ss->len == 0)\n" typ;
8555 pr " CAMLreturn (Atom (0));\n";
8557 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8558 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8559 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8560 pr " caml_modify (&Field (rv, i), v);\n";
8562 pr " CAMLreturn (rv);\n";
8570 let has_optpercent_col =
8571 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8573 pr "static CAMLprim value\n";
8574 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8576 pr " CAMLparam0 ();\n";
8577 if has_optpercent_col then
8578 pr " CAMLlocal3 (rv, v, v2);\n"
8580 pr " CAMLlocal2 (rv, v);\n";
8582 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8587 pr " v = caml_copy_string (%s->%s);\n" typ name
8589 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8590 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8593 pr " v = caml_alloc_string (32);\n";
8594 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8595 | name, (FBytes|FInt64|FUInt64) ->
8596 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8597 | name, (FInt32|FUInt32) ->
8598 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8599 | name, FOptPercent ->
8600 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8601 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8602 pr " v = caml_alloc (1, 0);\n";
8603 pr " Store_field (v, 0, v2);\n";
8604 pr " } else /* None */\n";
8605 pr " v = Val_int (0);\n";
8607 pr " v = Val_int (%s->%s);\n" typ name
8609 pr " Store_field (rv, %d, v);\n" i
8611 pr " CAMLreturn (rv);\n";
8616 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8619 | typ, (RStructListOnly | RStructAndList) ->
8620 (* generate the function for typ *)
8621 emit_ocaml_copy_list_function typ
8622 | typ, _ -> () (* empty *)
8623 ) (rstructs_used_by all_functions);
8627 fun (name, style, _, _, _, _, _) ->
8628 pr "/* Automatically generated wrapper for function\n";
8630 generate_ocaml_prototype name style;
8635 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8637 let needs_extra_vs =
8638 match fst style with RConstOptString _ -> true | _ -> false in
8640 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8641 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8642 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8645 pr "CAMLprim value\n";
8646 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8647 List.iter (pr ", value %s") (List.tl params);
8652 | [p1; p2; p3; p4; p5] ->
8653 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8654 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8655 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8656 pr " CAMLxparam%d (%s);\n"
8657 (List.length rest) (String.concat ", " rest)
8659 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8661 if not needs_extra_vs then
8662 pr " CAMLlocal1 (rv);\n"
8664 pr " CAMLlocal3 (rv, v, v2);\n";
8667 pr " guestfs_h *g = Guestfs_val (gv);\n";
8668 pr " if (g == NULL)\n";
8669 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8675 | Device n | Dev_or_Path n
8679 (* Copy strings in case the GC moves them: RHBZ#604691 *)
8680 pr " char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8682 pr " char *%s =\n" n;
8683 pr " %sv != Val_int (0) ?\n" n;
8684 pr " guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8686 pr " size_t %s_size = caml_string_length (%sv);\n" n n;
8687 pr " char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8688 | StringList n | DeviceList n ->
8689 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8691 pr " int %s = Bool_val (%sv);\n" n n
8693 pr " int %s = Int_val (%sv);\n" n n
8695 pr " int64_t %s = Int64_val (%sv);\n" n n
8698 match fst style with
8699 | RErr -> pr " int r;\n"; "-1"
8700 | RInt _ -> pr " int r;\n"; "-1"
8701 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8702 | RBool _ -> pr " int r;\n"; "-1"
8703 | RConstString _ | RConstOptString _ ->
8704 pr " const char *r;\n"; "NULL"
8705 | RString _ -> pr " char *r;\n"; "NULL"
8710 | RStruct (_, typ) ->
8711 pr " struct guestfs_%s *r;\n" typ; "NULL"
8712 | RStructList (_, typ) ->
8713 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8720 pr " size_t size;\n";
8724 pr " caml_enter_blocking_section ();\n";
8725 pr " r = guestfs_%s " name;
8726 generate_c_call_args ~handle:"g" style;
8728 pr " caml_leave_blocking_section ();\n";
8730 (* Free strings if we copied them above. *)
8733 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8734 | FileIn n | FileOut n | BufferIn n ->
8735 pr " free (%s);\n" n
8736 | StringList n | DeviceList n ->
8737 pr " ocaml_guestfs_free_strings (%s);\n" n;
8738 | Bool _ | Int _ | Int64 _ -> ()
8741 pr " if (r == %s)\n" error_code;
8742 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8745 (match fst style with
8746 | RErr -> pr " rv = Val_unit;\n"
8747 | RInt _ -> pr " rv = Val_int (r);\n"
8749 pr " rv = caml_copy_int64 (r);\n"
8750 | RBool _ -> pr " rv = Val_bool (r);\n"
8752 pr " rv = caml_copy_string (r);\n"
8753 | RConstOptString _ ->
8754 pr " if (r) { /* Some string */\n";
8755 pr " v = caml_alloc (1, 0);\n";
8756 pr " v2 = caml_copy_string (r);\n";
8757 pr " Store_field (v, 0, v2);\n";
8758 pr " } else /* None */\n";
8759 pr " v = Val_int (0);\n";
8761 pr " rv = caml_copy_string (r);\n";
8764 pr " rv = caml_copy_string_array ((const char **) r);\n";
8765 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8767 | RStruct (_, typ) ->
8768 pr " rv = copy_%s (r);\n" typ;
8769 pr " guestfs_free_%s (r);\n" typ;
8770 | RStructList (_, typ) ->
8771 pr " rv = copy_%s_list (r);\n" typ;
8772 pr " guestfs_free_%s_list (r);\n" typ;
8774 pr " rv = copy_table (r);\n";
8775 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8778 pr " rv = caml_alloc_string (size);\n";
8779 pr " memcpy (String_val (rv), r, size);\n";
8782 pr " CAMLreturn (rv);\n";
8786 if List.length params > 5 then (
8787 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8788 pr "CAMLprim value ";
8789 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8790 pr "CAMLprim value\n";
8791 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8793 pr " return ocaml_guestfs_%s (argv[0]" name;
8794 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8799 ) all_functions_sorted
8801 and generate_ocaml_structure_decls () =
8804 pr "type %s = {\n" typ;
8807 | name, FString -> pr " %s : string;\n" name
8808 | name, FBuffer -> pr " %s : string;\n" name
8809 | name, FUUID -> pr " %s : string;\n" name
8810 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8811 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8812 | name, FChar -> pr " %s : char;\n" name
8813 | name, FOptPercent -> pr " %s : float option;\n" name
8819 and generate_ocaml_prototype ?(is_external = false) name style =
8820 if is_external then pr "external " else pr "val ";
8821 pr "%s : t -> " name;
8824 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8825 | BufferIn _ -> pr "string -> "
8826 | OptString _ -> pr "string option -> "
8827 | StringList _ | DeviceList _ -> pr "string array -> "
8828 | Bool _ -> pr "bool -> "
8829 | Int _ -> pr "int -> "
8830 | Int64 _ -> pr "int64 -> "
8832 (match fst style with
8833 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8834 | RInt _ -> pr "int"
8835 | RInt64 _ -> pr "int64"
8836 | RBool _ -> pr "bool"
8837 | RConstString _ -> pr "string"
8838 | RConstOptString _ -> pr "string option"
8839 | RString _ | RBufferOut _ -> pr "string"
8840 | RStringList _ -> pr "string array"
8841 | RStruct (_, typ) -> pr "%s" typ
8842 | RStructList (_, typ) -> pr "%s array" typ
8843 | RHashtable _ -> pr "(string * string) list"
8845 if is_external then (
8847 if List.length (snd style) + 1 > 5 then
8848 pr "\"ocaml_guestfs_%s_byte\" " name;
8849 pr "\"ocaml_guestfs_%s\"" name
8853 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8854 and generate_perl_xs () =
8855 generate_header CStyle LGPLv2plus;
8858 #include \"EXTERN.h\"
8862 #include <guestfs.h>
8865 #define PRId64 \"lld\"
8869 my_newSVll(long long val) {
8870 #ifdef USE_64_BIT_ALL
8871 return newSViv(val);
8875 len = snprintf(buf, 100, \"%%\" PRId64, val);
8876 return newSVpv(buf, len);
8881 #define PRIu64 \"llu\"
8885 my_newSVull(unsigned long long val) {
8886 #ifdef USE_64_BIT_ALL
8887 return newSVuv(val);
8891 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8892 return newSVpv(buf, len);
8896 /* http://www.perlmonks.org/?node_id=680842 */
8898 XS_unpack_charPtrPtr (SV *arg) {
8903 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8904 croak (\"array reference expected\");
8906 av = (AV *)SvRV (arg);
8907 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8909 croak (\"malloc failed\");
8911 for (i = 0; i <= av_len (av); i++) {
8912 SV **elem = av_fetch (av, i, 0);
8914 if (!elem || !*elem)
8915 croak (\"missing element in list\");
8917 ret[i] = SvPV_nolen (*elem);
8925 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8932 RETVAL = guestfs_create ();
8934 croak (\"could not create guestfs handle\");
8935 guestfs_set_error_handler (RETVAL, NULL, NULL);
8943 /* For the 'g' argument above we do the conversion explicitly and
8944 * don't rely on the typemap, because if the handle has been
8945 * explicitly closed we don't want the typemap conversion to
8948 HV *hv = (HV *) SvRV (sv);
8949 SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8951 guestfs_h *g = (guestfs_h *) SvIV (*svp);
8961 /* Avoid double-free in DESTROY method. */
8962 HV *hv = (HV *) SvRV (ST(0));
8963 (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8968 fun (name, style, _, _, _, _, _) ->
8969 (match fst style with
8970 | RErr -> pr "void\n"
8971 | RInt _ -> pr "SV *\n"
8972 | RInt64 _ -> pr "SV *\n"
8973 | RBool _ -> pr "SV *\n"
8974 | RConstString _ -> pr "SV *\n"
8975 | RConstOptString _ -> pr "SV *\n"
8976 | RString _ -> pr "SV *\n"
8977 | RBufferOut _ -> pr "SV *\n"
8979 | RStruct _ | RStructList _
8981 pr "void\n" (* all lists returned implictly on the stack *)
8983 (* Call and arguments. *)
8986 fun arg -> pr ", %s" (name_of_argt arg)
8989 pr " guestfs_h *g;\n";
8993 | Pathname n | Device n | Dev_or_Path n | String n
8994 | FileIn n | FileOut n ->
8997 pr " char *%s;\n" n;
8998 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
9000 (* http://www.perlmonks.org/?node_id=554277
9001 * Note that the implicit handle argument means we have
9002 * to add 1 to the ST(x) operator.
9004 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9005 | StringList n | DeviceList n -> pr " char **%s;\n" n
9006 | Bool n -> pr " int %s;\n" n
9007 | Int n -> pr " int %s;\n" n
9008 | Int64 n -> pr " int64_t %s;\n" n
9011 let do_cleanups () =
9014 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9015 | Bool _ | Int _ | Int64 _
9016 | FileIn _ | FileOut _
9018 | StringList n | DeviceList n -> pr " free (%s);\n" n
9023 (match fst style with
9028 pr " r = guestfs_%s " name;
9029 generate_c_call_args ~handle:"g" style;
9032 pr " if (r == -1)\n";
9033 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9039 pr " %s = guestfs_%s " n name;
9040 generate_c_call_args ~handle:"g" style;
9043 pr " if (%s == -1)\n" n;
9044 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9045 pr " RETVAL = newSViv (%s);\n" n;
9050 pr " int64_t %s;\n" n;
9052 pr " %s = guestfs_%s " n name;
9053 generate_c_call_args ~handle:"g" style;
9056 pr " if (%s == -1)\n" n;
9057 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9058 pr " RETVAL = my_newSVll (%s);\n" n;
9063 pr " const char *%s;\n" n;
9065 pr " %s = guestfs_%s " n name;
9066 generate_c_call_args ~handle:"g" style;
9069 pr " if (%s == NULL)\n" n;
9070 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9071 pr " RETVAL = newSVpv (%s, 0);\n" n;
9074 | RConstOptString n ->
9076 pr " const char *%s;\n" n;
9078 pr " %s = guestfs_%s " n name;
9079 generate_c_call_args ~handle:"g" style;
9082 pr " if (%s == NULL)\n" n;
9083 pr " RETVAL = &PL_sv_undef;\n";
9085 pr " RETVAL = newSVpv (%s, 0);\n" n;
9090 pr " char *%s;\n" n;
9092 pr " %s = guestfs_%s " n name;
9093 generate_c_call_args ~handle:"g" style;
9096 pr " if (%s == NULL)\n" n;
9097 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9098 pr " RETVAL = newSVpv (%s, 0);\n" n;
9099 pr " free (%s);\n" n;
9102 | RStringList n | RHashtable n ->
9104 pr " char **%s;\n" n;
9105 pr " size_t i, n;\n";
9107 pr " %s = guestfs_%s " n name;
9108 generate_c_call_args ~handle:"g" style;
9111 pr " if (%s == NULL)\n" n;
9112 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9113 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9114 pr " EXTEND (SP, n);\n";
9115 pr " for (i = 0; i < n; ++i) {\n";
9116 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9117 pr " free (%s[i]);\n" n;
9119 pr " free (%s);\n" n;
9120 | RStruct (n, typ) ->
9121 let cols = cols_of_struct typ in
9122 generate_perl_struct_code typ cols name style n do_cleanups
9123 | RStructList (n, typ) ->
9124 let cols = cols_of_struct typ in
9125 generate_perl_struct_list_code typ cols name style n do_cleanups
9128 pr " char *%s;\n" n;
9129 pr " size_t size;\n";
9131 pr " %s = guestfs_%s " n name;
9132 generate_c_call_args ~handle:"g" style;
9135 pr " if (%s == NULL)\n" n;
9136 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9137 pr " RETVAL = newSVpvn (%s, size);\n" n;
9138 pr " free (%s);\n" n;
9146 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9148 pr " struct guestfs_%s_list *%s;\n" typ n;
9152 pr " %s = guestfs_%s " n name;
9153 generate_c_call_args ~handle:"g" style;
9156 pr " if (%s == NULL)\n" n;
9157 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9158 pr " EXTEND (SP, %s->len);\n" n;
9159 pr " for (i = 0; i < %s->len; ++i) {\n" n;
9160 pr " hv = newHV ();\n";
9164 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9165 name (String.length name) n name
9167 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9168 name (String.length name) n name
9170 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9171 name (String.length name) n name n name
9172 | name, (FBytes|FUInt64) ->
9173 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9174 name (String.length name) n name
9176 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9177 name (String.length name) n name
9178 | name, (FInt32|FUInt32) ->
9179 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9180 name (String.length name) n name
9182 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9183 name (String.length name) n name
9184 | name, FOptPercent ->
9185 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9186 name (String.length name) n name
9188 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9190 pr " guestfs_free_%s_list (%s);\n" typ n
9192 and generate_perl_struct_code typ cols name style n do_cleanups =
9194 pr " struct guestfs_%s *%s;\n" typ n;
9196 pr " %s = guestfs_%s " n name;
9197 generate_c_call_args ~handle:"g" style;
9200 pr " if (%s == NULL)\n" n;
9201 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9202 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
9204 fun ((name, _) as col) ->
9205 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9209 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9212 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9215 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9217 | name, (FBytes|FUInt64) ->
9218 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9221 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9223 | name, (FInt32|FUInt32) ->
9224 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9227 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9229 | name, FOptPercent ->
9230 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9233 pr " free (%s);\n" n
9235 (* Generate Sys/Guestfs.pm. *)
9236 and generate_perl_pm () =
9237 generate_header HashStyle LGPLv2plus;
9244 Sys::Guestfs - Perl bindings for libguestfs
9250 my $h = Sys::Guestfs->new ();
9251 $h->add_drive ('guest.img');
9253 $h->mount ('/dev/sda1', '/');
9254 $h->touch ('/hello');
9259 The C<Sys::Guestfs> module provides a Perl XS binding to the
9260 libguestfs API for examining and modifying virtual machine
9263 Amongst the things this is good for: making batch configuration
9264 changes to guests, getting disk used/free statistics (see also:
9265 virt-df), migrating between virtualization systems (see also:
9266 virt-p2v), performing partial backups, performing partial guest
9267 clones, cloning guests and changing registry/UUID/hostname info, and
9270 Libguestfs uses Linux kernel and qemu code, and can access any type of
9271 guest filesystem that Linux and qemu can, including but not limited
9272 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9273 schemes, qcow, qcow2, vmdk.
9275 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9276 LVs, what filesystem is in each LV, etc.). It can also run commands
9277 in the context of the guest. Also you can access filesystems over
9280 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9281 functions for using libguestfs from Perl, including integration
9286 All errors turn into calls to C<croak> (see L<Carp(3)>).
9294 package Sys::Guestfs;
9299 # This version number changes whenever a new function
9300 # is added to the libguestfs API. It is not directly
9301 # related to the libguestfs version number.
9302 use vars qw($VERSION);
9306 XSLoader::load ('Sys::Guestfs');
9308 =item $h = Sys::Guestfs->new ();
9310 Create a new guestfs handle.
9316 my $class = ref ($proto) || $proto;
9318 my $g = Sys::Guestfs::_create ();
9319 my $self = { _g => $g };
9320 bless $self, $class;
9326 Explicitly close the guestfs handle.
9328 B<Note:> You should not usually call this function. The handle will
9329 be closed implicitly when its reference count goes to zero (eg.
9330 when it goes out of scope or the program ends). This call is
9331 only required in some exceptional cases, such as where the program
9332 may contain cached references to the handle 'somewhere' and you
9333 really have to have the close happen right away. After calling
9334 C<close> the program must not call any method (including C<close>)
9335 on the handle (but the implicit call to C<DESTROY> that happens
9336 when the final reference is cleaned up is OK).
9342 (* Actions. We only need to print documentation for these as
9343 * they are pulled in from the XS code automatically.
9346 fun (name, style, _, flags, _, _, longdesc) ->
9347 if not (List.mem NotInDocs flags) then (
9348 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9350 generate_perl_prototype name style;
9352 pr "%s\n\n" longdesc;
9353 if List.mem ProtocolLimitWarning flags then
9354 pr "%s\n\n" protocol_limit_warning;
9355 if List.mem DangerWillRobinson flags then
9356 pr "%s\n\n" danger_will_robinson;
9357 match deprecation_notice flags with
9359 | Some txt -> pr "%s\n\n" txt
9361 ) all_functions_sorted;
9373 From time to time we add new libguestfs APIs. Also some libguestfs
9374 APIs won't be available in all builds of libguestfs (the Fedora
9375 build is full-featured, but other builds may disable features).
9376 How do you test whether the APIs that your Perl program needs are
9377 available in the version of C<Sys::Guestfs> that you are using?
9379 To test if a particular function is available in the C<Sys::Guestfs>
9380 class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
9381 (see L<perlobj(1)>). For example:
9384 if (defined (Sys::Guestfs->can (\"set_verbose\"))) {
9385 print \"\\$h->set_verbose is available\\n\";
9388 To test if particular features are supported by the current
9389 build, use the L</available> method like the example below. Note
9390 that the appliance must be launched first.
9392 $h->available ( [\"augeas\"] );
9394 Since the L</available> method croaks if the feature is not supported,
9395 you might also want to wrap this in an eval and return a boolean.
9396 In fact this has already been done for you: use
9397 L<Sys::Guestfs::Lib(3)/feature_available>.
9399 For further discussion on this topic, refer to
9400 L<guestfs(3)/AVAILABILITY>.
9402 =head1 STORING DATA IN THE HANDLE
9404 The handle returned from L</new> is a hash reference. The hash
9405 normally contains a single element:
9408 _g => [private data used by libguestfs]
9411 Callers can add other elements to this hash to store data for their own
9412 purposes. The data lasts for the lifetime of the handle.
9414 Any fields whose names begin with an underscore are reserved
9415 for private use by libguestfs. We may add more in future.
9417 It is recommended that callers prefix the name of their field(s)
9418 with some unique string, to avoid conflicts with other users.
9422 Copyright (C) %s Red Hat Inc.
9426 Please see the file COPYING.LIB for the full license.
9432 L<http://libguestfs.org>,
9433 L<Sys::Guestfs::Lib(3)>.
9438 and generate_perl_prototype name style =
9439 (match fst style with
9447 | RBufferOut n -> pr "$%s = " n
9449 | RHashtable n -> pr "%%%s = " n
9451 | RStructList (n,_) -> pr "@%s = " n
9454 let comma = ref false in
9457 if !comma then pr ", ";
9460 | Pathname n | Device n | Dev_or_Path n | String n
9461 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9464 | StringList n | DeviceList n ->
9469 (* Generate Python C module. *)
9470 and generate_python_c () =
9471 generate_header CStyle LGPLv2plus;
9474 #define PY_SSIZE_T_CLEAN 1
9477 #if PY_VERSION_HEX < 0x02050000
9478 typedef int Py_ssize_t;
9479 #define PY_SSIZE_T_MAX INT_MAX
9480 #define PY_SSIZE_T_MIN INT_MIN
9487 #include \"guestfs.h\"
9495 get_handle (PyObject *obj)
9498 assert (obj != Py_None);
9499 return ((Pyguestfs_Object *) obj)->g;
9503 put_handle (guestfs_h *g)
9507 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9510 /* This list should be freed (but not the strings) after use. */
9512 get_string_list (PyObject *obj)
9519 if (!PyList_Check (obj)) {
9520 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9524 Py_ssize_t slen = PyList_Size (obj);
9526 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9529 len = (size_t) slen;
9530 r = malloc (sizeof (char *) * (len+1));
9532 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9536 for (i = 0; i < len; ++i)
9537 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9544 put_string_list (char * const * const argv)
9549 for (argc = 0; argv[argc] != NULL; ++argc)
9552 list = PyList_New (argc);
9553 for (i = 0; i < argc; ++i)
9554 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9560 put_table (char * const * const argv)
9562 PyObject *list, *item;
9565 for (argc = 0; argv[argc] != NULL; ++argc)
9568 list = PyList_New (argc >> 1);
9569 for (i = 0; i < argc; i += 2) {
9570 item = PyTuple_New (2);
9571 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9572 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9573 PyList_SetItem (list, i >> 1, item);
9580 free_strings (char **argv)
9584 for (argc = 0; argv[argc] != NULL; ++argc)
9590 py_guestfs_create (PyObject *self, PyObject *args)
9594 g = guestfs_create ();
9596 PyErr_SetString (PyExc_RuntimeError,
9597 \"guestfs.create: failed to allocate handle\");
9600 guestfs_set_error_handler (g, NULL, NULL);
9601 return put_handle (g);
9605 py_guestfs_close (PyObject *self, PyObject *args)
9610 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9612 g = get_handle (py_g);
9616 Py_INCREF (Py_None);
9622 let emit_put_list_function typ =
9623 pr "static PyObject *\n";
9624 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9626 pr " PyObject *list;\n";
9629 pr " list = PyList_New (%ss->len);\n" typ;
9630 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9631 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9632 pr " return list;\n";
9637 (* Structures, turned into Python dictionaries. *)
9640 pr "static PyObject *\n";
9641 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9643 pr " PyObject *dict;\n";
9645 pr " dict = PyDict_New ();\n";
9649 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9650 pr " PyString_FromString (%s->%s));\n"
9653 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9654 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9657 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9658 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9660 | name, (FBytes|FUInt64) ->
9661 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9662 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9665 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9666 pr " PyLong_FromLongLong (%s->%s));\n"
9669 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9670 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9673 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9674 pr " PyLong_FromLong (%s->%s));\n"
9676 | name, FOptPercent ->
9677 pr " if (%s->%s >= 0)\n" typ name;
9678 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9679 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9682 pr " Py_INCREF (Py_None);\n";
9683 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9686 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9687 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9689 pr " return dict;\n";
9695 (* Emit a put_TYPE_list function definition only if that function is used. *)
9698 | typ, (RStructListOnly | RStructAndList) ->
9699 (* generate the function for typ *)
9700 emit_put_list_function typ
9701 | typ, _ -> () (* empty *)
9702 ) (rstructs_used_by all_functions);
9704 (* Python wrapper functions. *)
9706 fun (name, style, _, _, _, _, _) ->
9707 pr "static PyObject *\n";
9708 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9711 pr " PyObject *py_g;\n";
9712 pr " guestfs_h *g;\n";
9713 pr " PyObject *py_r;\n";
9716 match fst style with
9717 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9718 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9719 | RConstString _ | RConstOptString _ ->
9720 pr " const char *r;\n"; "NULL"
9721 | RString _ -> pr " char *r;\n"; "NULL"
9722 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9723 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9724 | RStructList (_, typ) ->
9725 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9728 pr " size_t size;\n";
9733 | Pathname n | Device n | Dev_or_Path n | String n
9734 | FileIn n | FileOut n ->
9735 pr " const char *%s;\n" n
9736 | OptString n -> pr " const char *%s;\n" n
9738 pr " const char *%s;\n" n;
9739 pr " Py_ssize_t %s_size;\n" n
9740 | StringList n | DeviceList n ->
9741 pr " PyObject *py_%s;\n" n;
9742 pr " char **%s;\n" n
9743 | Bool n -> pr " int %s;\n" n
9744 | Int n -> pr " int %s;\n" n
9745 | Int64 n -> pr " long long %s;\n" n
9750 (* Convert the parameters. *)
9751 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9754 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9755 | OptString _ -> pr "z"
9756 | StringList _ | DeviceList _ -> pr "O"
9757 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9759 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9760 * emulate C's int/long/long long in Python?
9762 | BufferIn _ -> pr "s#"
9764 pr ":guestfs_%s\",\n" name;
9768 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9769 | OptString n -> pr ", &%s" n
9770 | StringList n | DeviceList n -> pr ", &py_%s" n
9771 | Bool n -> pr ", &%s" n
9772 | Int n -> pr ", &%s" n
9773 | Int64 n -> pr ", &%s" n
9774 | BufferIn n -> pr ", &%s, &%s_size" n n
9778 pr " return NULL;\n";
9780 pr " g = get_handle (py_g);\n";
9783 | Pathname _ | Device _ | Dev_or_Path _ | String _
9784 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9786 | StringList n | DeviceList n ->
9787 pr " %s = get_string_list (py_%s);\n" n n;
9788 pr " if (!%s) return NULL;\n" n
9793 pr " r = guestfs_%s " name;
9794 generate_c_call_args ~handle:"g" style;
9799 | Pathname _ | Device _ | Dev_or_Path _ | String _
9800 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9802 | StringList n | DeviceList n ->
9803 pr " free (%s);\n" n
9806 pr " if (r == %s) {\n" error_code;
9807 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9808 pr " return NULL;\n";
9812 (match fst style with
9814 pr " Py_INCREF (Py_None);\n";
9815 pr " py_r = Py_None;\n"
9817 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9818 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9819 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9820 | RConstOptString _ ->
9822 pr " py_r = PyString_FromString (r);\n";
9824 pr " Py_INCREF (Py_None);\n";
9825 pr " py_r = Py_None;\n";
9828 pr " py_r = PyString_FromString (r);\n";
9831 pr " py_r = put_string_list (r);\n";
9832 pr " free_strings (r);\n"
9833 | RStruct (_, typ) ->
9834 pr " py_r = put_%s (r);\n" typ;
9835 pr " guestfs_free_%s (r);\n" typ
9836 | RStructList (_, typ) ->
9837 pr " py_r = put_%s_list (r);\n" typ;
9838 pr " guestfs_free_%s_list (r);\n" typ
9840 pr " py_r = put_table (r);\n";
9841 pr " free_strings (r);\n"
9843 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9847 pr " return py_r;\n";
9852 (* Table of functions. *)
9853 pr "static PyMethodDef methods[] = {\n";
9854 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9855 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9857 fun (name, _, _, _, _, _, _) ->
9858 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9861 pr " { NULL, NULL, 0, NULL }\n";
9865 (* Init function. *)
9868 initlibguestfsmod (void)
9870 static int initialized = 0;
9872 if (initialized) return;
9873 Py_InitModule ((char *) \"libguestfsmod\", methods);
9878 (* Generate Python module. *)
9879 and generate_python_py () =
9880 generate_header HashStyle LGPLv2plus;
9883 u\"\"\"Python bindings for libguestfs
9886 g = guestfs.GuestFS ()
9887 g.add_drive (\"guest.img\")
9889 parts = g.list_partitions ()
9891 The guestfs module provides a Python binding to the libguestfs API
9892 for examining and modifying virtual machine disk images.
9894 Amongst the things this is good for: making batch configuration
9895 changes to guests, getting disk used/free statistics (see also:
9896 virt-df), migrating between virtualization systems (see also:
9897 virt-p2v), performing partial backups, performing partial guest
9898 clones, cloning guests and changing registry/UUID/hostname info, and
9901 Libguestfs uses Linux kernel and qemu code, and can access any type of
9902 guest filesystem that Linux and qemu can, including but not limited
9903 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9904 schemes, qcow, qcow2, vmdk.
9906 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9907 LVs, what filesystem is in each LV, etc.). It can also run commands
9908 in the context of the guest. Also you can access filesystems over
9911 Errors which happen while using the API are turned into Python
9912 RuntimeError exceptions.
9914 To create a guestfs handle you usually have to perform the following
9917 # Create the handle, call add_drive at least once, and possibly
9918 # several times if the guest has multiple block devices:
9919 g = guestfs.GuestFS ()
9920 g.add_drive (\"guest.img\")
9922 # Launch the qemu subprocess and wait for it to become ready:
9925 # Now you can issue commands, for example:
9930 import libguestfsmod
9933 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9935 def __init__ (self):
9936 \"\"\"Create a new libguestfs handle.\"\"\"
9937 self._o = libguestfsmod.create ()
9940 libguestfsmod.close (self._o)
9945 fun (name, style, _, flags, _, _, longdesc) ->
9947 generate_py_call_args ~handle:"self" (snd style);
9950 if not (List.mem NotInDocs flags) then (
9951 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9953 match fst style with
9954 | RErr | RInt _ | RInt64 _ | RBool _
9955 | RConstOptString _ | RConstString _
9956 | RString _ | RBufferOut _ -> doc
9958 doc ^ "\n\nThis function returns a list of strings."
9959 | RStruct (_, typ) ->
9960 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9961 | RStructList (_, typ) ->
9962 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9964 doc ^ "\n\nThis function returns a dictionary." in
9966 if List.mem ProtocolLimitWarning flags then
9967 doc ^ "\n\n" ^ protocol_limit_warning
9970 if List.mem DangerWillRobinson flags then
9971 doc ^ "\n\n" ^ danger_will_robinson
9974 match deprecation_notice flags with
9976 | Some txt -> doc ^ "\n\n" ^ txt in
9977 let doc = pod2text ~width:60 name doc in
9978 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9979 let doc = String.concat "\n " doc in
9980 pr " u\"\"\"%s\"\"\"\n" doc;
9982 pr " return libguestfsmod.%s " name;
9983 generate_py_call_args ~handle:"self._o" (snd style);
9988 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9989 and generate_py_call_args ~handle args =
9991 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9994 (* Useful if you need the longdesc POD text as plain text. Returns a
9997 * Because this is very slow (the slowest part of autogeneration),
9998 * we memoize the results.
10000 and pod2text ~width name longdesc =
10001 let key = width, name, longdesc in
10002 try Hashtbl.find pod2text_memo key
10004 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10005 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10007 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10008 let chan = open_process_in cmd in
10009 let lines = ref [] in
10011 let line = input_line chan in
10012 if i = 1 then (* discard the first line of output *)
10015 let line = triml line in
10016 lines := line :: !lines;
10019 let lines = try loop 1 with End_of_file -> List.rev !lines in
10021 (match close_process_in chan with
10024 failwithf "pod2text: process exited with non-zero status (%d)" i
10025 | WSIGNALED i | WSTOPPED i ->
10026 failwithf "pod2text: process signalled or stopped by signal %d" i
10028 Hashtbl.add pod2text_memo key lines;
10029 pod2text_memo_updated ();
10032 (* Generate ruby bindings. *)
10033 and generate_ruby_c () =
10034 generate_header CStyle LGPLv2plus;
10038 #include <stdlib.h>
10042 #include \"guestfs.h\"
10044 #include \"extconf.h\"
10046 /* For Ruby < 1.9 */
10048 #define RARRAY_LEN(r) (RARRAY((r))->len)
10051 static VALUE m_guestfs; /* guestfs module */
10052 static VALUE c_guestfs; /* guestfs_h handle */
10053 static VALUE e_Error; /* used for all errors */
10055 static void ruby_guestfs_free (void *p)
10058 guestfs_close ((guestfs_h *) p);
10061 static VALUE ruby_guestfs_create (VALUE m)
10065 g = guestfs_create ();
10067 rb_raise (e_Error, \"failed to create guestfs handle\");
10069 /* Don't print error messages to stderr by default. */
10070 guestfs_set_error_handler (g, NULL, NULL);
10072 /* Wrap it, and make sure the close function is called when the
10073 * handle goes away.
10075 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10078 static VALUE ruby_guestfs_close (VALUE gv)
10081 Data_Get_Struct (gv, guestfs_h, g);
10083 ruby_guestfs_free (g);
10084 DATA_PTR (gv) = NULL;
10092 fun (name, style, _, _, _, _, _) ->
10093 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10094 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10097 pr " guestfs_h *g;\n";
10098 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
10100 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10106 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
10107 pr " Check_Type (%sv, T_STRING);\n" n;
10108 pr " const char *%s = StringValueCStr (%sv);\n" n n;
10109 pr " if (!%s)\n" n;
10110 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10111 pr " \"%s\", \"%s\");\n" n name
10113 pr " Check_Type (%sv, T_STRING);\n" n;
10114 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
10115 pr " if (!%s)\n" n;
10116 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10117 pr " \"%s\", \"%s\");\n" n name;
10118 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
10120 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10121 | StringList n | DeviceList n ->
10122 pr " char **%s;\n" n;
10123 pr " Check_Type (%sv, T_ARRAY);\n" n;
10125 pr " size_t i, len;\n";
10126 pr " len = RARRAY_LEN (%sv);\n" n;
10127 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10129 pr " for (i = 0; i < len; ++i) {\n";
10130 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
10131 pr " %s[i] = StringValueCStr (v);\n" n;
10133 pr " %s[len] = NULL;\n" n;
10136 pr " int %s = RTEST (%sv);\n" n n
10138 pr " int %s = NUM2INT (%sv);\n" n n
10140 pr " long long %s = NUM2LL (%sv);\n" n n
10145 match fst style with
10146 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
10147 | RInt64 _ -> pr " int64_t r;\n"; "-1"
10148 | RConstString _ | RConstOptString _ ->
10149 pr " const char *r;\n"; "NULL"
10150 | RString _ -> pr " char *r;\n"; "NULL"
10151 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
10152 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
10153 | RStructList (_, typ) ->
10154 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
10157 pr " size_t size;\n";
10161 pr " r = guestfs_%s " name;
10162 generate_c_call_args ~handle:"g" style;
10167 | Pathname _ | Device _ | Dev_or_Path _ | String _
10168 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10170 | StringList n | DeviceList n ->
10171 pr " free (%s);\n" n
10174 pr " if (r == %s)\n" error_code;
10175 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10178 (match fst style with
10180 pr " return Qnil;\n"
10181 | RInt _ | RBool _ ->
10182 pr " return INT2NUM (r);\n"
10184 pr " return ULL2NUM (r);\n"
10185 | RConstString _ ->
10186 pr " return rb_str_new2 (r);\n";
10187 | RConstOptString _ ->
10189 pr " return rb_str_new2 (r);\n";
10191 pr " return Qnil;\n";
10193 pr " VALUE rv = rb_str_new2 (r);\n";
10195 pr " return rv;\n";
10197 pr " size_t i, len = 0;\n";
10198 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
10199 pr " VALUE rv = rb_ary_new2 (len);\n";
10200 pr " for (i = 0; r[i] != NULL; ++i) {\n";
10201 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10202 pr " free (r[i]);\n";
10206 | RStruct (_, typ) ->
10207 let cols = cols_of_struct typ in
10208 generate_ruby_struct_code typ cols
10209 | RStructList (_, typ) ->
10210 let cols = cols_of_struct typ in
10211 generate_ruby_struct_list_code typ cols
10213 pr " VALUE rv = rb_hash_new ();\n";
10215 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
10216 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10217 pr " free (r[i]);\n";
10218 pr " free (r[i+1]);\n";
10223 pr " VALUE rv = rb_str_new (r, size);\n";
10225 pr " return rv;\n";
10233 /* Initialize the module. */
10234 void Init__guestfs ()
10236 m_guestfs = rb_define_module (\"Guestfs\");
10237 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10238 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10240 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10241 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10244 (* Define the rest of the methods. *)
10246 fun (name, style, _, _, _, _, _) ->
10247 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
10248 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10253 (* Ruby code to return a struct. *)
10254 and generate_ruby_struct_code typ cols =
10255 pr " VALUE rv = rb_hash_new ();\n";
10259 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10261 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10263 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10264 | name, (FBytes|FUInt64) ->
10265 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10267 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10269 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10271 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10272 | name, FOptPercent ->
10273 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10274 | name, FChar -> (* XXX wrong? *)
10275 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10277 pr " guestfs_free_%s (r);\n" typ;
10280 (* Ruby code to return a struct list. *)
10281 and generate_ruby_struct_list_code typ cols =
10282 pr " VALUE rv = rb_ary_new2 (r->len);\n";
10284 pr " for (i = 0; i < r->len; ++i) {\n";
10285 pr " VALUE hv = rb_hash_new ();\n";
10289 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10291 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
10293 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10294 | name, (FBytes|FUInt64) ->
10295 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10297 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10299 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10301 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10302 | name, FOptPercent ->
10303 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10304 | name, FChar -> (* XXX wrong? *)
10305 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10307 pr " rb_ary_push (rv, hv);\n";
10309 pr " guestfs_free_%s_list (r);\n" typ;
10312 (* Generate Java bindings GuestFS.java file. *)
10313 and generate_java_java () =
10314 generate_header CStyle LGPLv2plus;
10317 package com.redhat.et.libguestfs;
10319 import java.util.HashMap;
10320 import com.redhat.et.libguestfs.LibGuestFSException;
10321 import com.redhat.et.libguestfs.PV;
10322 import com.redhat.et.libguestfs.VG;
10323 import com.redhat.et.libguestfs.LV;
10324 import com.redhat.et.libguestfs.Stat;
10325 import com.redhat.et.libguestfs.StatVFS;
10326 import com.redhat.et.libguestfs.IntBool;
10327 import com.redhat.et.libguestfs.Dirent;
10330 * The GuestFS object is a libguestfs handle.
10334 public class GuestFS {
10335 // Load the native code.
10337 System.loadLibrary (\"guestfs_jni\");
10341 * The native guestfs_h pointer.
10346 * Create a libguestfs handle.
10348 * @throws LibGuestFSException
10350 public GuestFS () throws LibGuestFSException
10354 private native long _create () throws LibGuestFSException;
10357 * Close a libguestfs handle.
10359 * You can also leave handles to be collected by the garbage
10360 * collector, but this method ensures that the resources used
10361 * by the handle are freed up immediately. If you call any
10362 * other methods after closing the handle, you will get an
10365 * @throws LibGuestFSException
10367 public void close () throws LibGuestFSException
10373 private native void _close (long g) throws LibGuestFSException;
10375 public void finalize () throws LibGuestFSException
10383 fun (name, style, _, flags, _, shortdesc, longdesc) ->
10384 if not (List.mem NotInDocs flags); then (
10385 let doc = replace_str longdesc "C<guestfs_" "C<g." in
10387 if List.mem ProtocolLimitWarning flags then
10388 doc ^ "\n\n" ^ protocol_limit_warning
10391 if List.mem DangerWillRobinson flags then
10392 doc ^ "\n\n" ^ danger_will_robinson
10395 match deprecation_notice flags with
10397 | Some txt -> doc ^ "\n\n" ^ txt in
10398 let doc = pod2text ~width:60 name doc in
10399 let doc = List.map ( (* RHBZ#501883 *)
10402 | nonempty -> nonempty
10404 let doc = String.concat "\n * " doc in
10407 pr " * %s\n" shortdesc;
10410 pr " * @throws LibGuestFSException\n";
10414 generate_java_prototype ~public:true ~semicolon:false name style;
10417 pr " if (g == 0)\n";
10418 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
10421 if fst style <> RErr then pr "return ";
10423 generate_java_call_args ~handle:"g" (snd style);
10427 generate_java_prototype ~privat:true ~native:true name style;
10434 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10435 and generate_java_call_args ~handle args =
10437 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10440 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10441 ?(semicolon=true) name style =
10442 if privat then pr "private ";
10443 if public then pr "public ";
10444 if native then pr "native ";
10447 (match fst style with
10448 | RErr -> pr "void ";
10449 | RInt _ -> pr "int ";
10450 | RInt64 _ -> pr "long ";
10451 | RBool _ -> pr "boolean ";
10452 | RConstString _ | RConstOptString _ | RString _
10453 | RBufferOut _ -> pr "String ";
10454 | RStringList _ -> pr "String[] ";
10455 | RStruct (_, typ) ->
10456 let name = java_name_of_struct typ in
10458 | RStructList (_, typ) ->
10459 let name = java_name_of_struct typ in
10461 | RHashtable _ -> pr "HashMap<String,String> ";
10464 if native then pr "_%s " name else pr "%s " name;
10466 let needs_comma = ref false in
10469 needs_comma := true
10475 if !needs_comma then pr ", ";
10476 needs_comma := true;
10480 | Device n | Dev_or_Path n
10488 | StringList n | DeviceList n ->
10499 pr " throws LibGuestFSException";
10500 if semicolon then pr ";"
10502 and generate_java_struct jtyp cols () =
10503 generate_header CStyle LGPLv2plus;
10506 package com.redhat.et.libguestfs;
10509 * Libguestfs %s structure.
10521 | name, FBuffer -> pr " public String %s;\n" name
10522 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10523 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10524 | name, FChar -> pr " public char %s;\n" name
10525 | name, FOptPercent ->
10526 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10527 pr " public float %s;\n" name
10532 and generate_java_c () =
10533 generate_header CStyle LGPLv2plus;
10537 #include <stdlib.h>
10538 #include <string.h>
10540 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10541 #include \"guestfs.h\"
10543 /* Note that this function returns. The exception is not thrown
10544 * until after the wrapper function returns.
10547 throw_exception (JNIEnv *env, const char *msg)
10550 cl = (*env)->FindClass (env,
10551 \"com/redhat/et/libguestfs/LibGuestFSException\");
10552 (*env)->ThrowNew (env, cl, msg);
10555 JNIEXPORT jlong JNICALL
10556 Java_com_redhat_et_libguestfs_GuestFS__1create
10557 (JNIEnv *env, jobject obj)
10561 g = guestfs_create ();
10563 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10566 guestfs_set_error_handler (g, NULL, NULL);
10567 return (jlong) (long) g;
10570 JNIEXPORT void JNICALL
10571 Java_com_redhat_et_libguestfs_GuestFS__1close
10572 (JNIEnv *env, jobject obj, jlong jg)
10574 guestfs_h *g = (guestfs_h *) (long) jg;
10581 fun (name, style, _, _, _, _, _) ->
10583 (match fst style with
10584 | RErr -> pr "void ";
10585 | RInt _ -> pr "jint ";
10586 | RInt64 _ -> pr "jlong ";
10587 | RBool _ -> pr "jboolean ";
10588 | RConstString _ | RConstOptString _ | RString _
10589 | RBufferOut _ -> pr "jstring ";
10590 | RStruct _ | RHashtable _ ->
10592 | RStringList _ | RStructList _ ->
10593 pr "jobjectArray ";
10596 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10597 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10599 pr " (JNIEnv *env, jobject obj, jlong jg";
10603 | Device n | Dev_or_Path n
10608 pr ", jstring j%s" n
10610 pr ", jbyteArray j%s" n
10611 | StringList n | DeviceList n ->
10612 pr ", jobjectArray j%s" n
10614 pr ", jboolean j%s" n
10622 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10623 let error_code, no_ret =
10624 match fst style with
10625 | RErr -> pr " int r;\n"; "-1", ""
10627 | RInt _ -> pr " int r;\n"; "-1", "0"
10628 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10629 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10630 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10632 pr " jstring jr;\n";
10633 pr " char *r;\n"; "NULL", "NULL"
10635 pr " jobjectArray jr;\n";
10636 pr " int r_len;\n";
10637 pr " jclass cl;\n";
10638 pr " jstring jstr;\n";
10639 pr " char **r;\n"; "NULL", "NULL"
10640 | RStruct (_, typ) ->
10641 pr " jobject jr;\n";
10642 pr " jclass cl;\n";
10643 pr " jfieldID fl;\n";
10644 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10645 | RStructList (_, typ) ->
10646 pr " jobjectArray jr;\n";
10647 pr " jclass cl;\n";
10648 pr " jfieldID fl;\n";
10649 pr " jobject jfl;\n";
10650 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10651 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10653 pr " jstring jr;\n";
10655 pr " size_t size;\n";
10660 | Device n | Dev_or_Path n
10665 pr " const char *%s;\n" n
10667 pr " jbyte *%s;\n" n;
10668 pr " size_t %s_size;\n" n
10669 | StringList n | DeviceList n ->
10670 pr " int %s_len;\n" n;
10671 pr " const char **%s;\n" n
10676 pr " int64_t %s;\n" n
10680 (match fst style with
10681 | RStringList _ | RStructList _ -> true
10682 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10683 | RConstOptString _
10684 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10685 List.exists (function
10686 | StringList _ -> true
10687 | DeviceList _ -> true
10688 | _ -> false) (snd style) in
10694 (* Get the parameters. *)
10698 | Device n | Dev_or_Path n
10702 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10704 (* This is completely undocumented, but Java null becomes
10705 * a NULL parameter.
10707 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10709 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10710 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10711 | StringList n | DeviceList n ->
10712 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10713 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10714 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10715 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10717 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10719 pr " %s[%s_len] = NULL;\n" n n;
10723 pr " %s = j%s;\n" n n
10726 (* Make the call. *)
10727 pr " r = guestfs_%s " name;
10728 generate_c_call_args ~handle:"g" style;
10731 (* Release the parameters. *)
10735 | Device n | Dev_or_Path n
10739 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10741 pr " if (j%s)\n" n;
10742 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10744 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10745 | StringList n | DeviceList n ->
10746 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10747 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10749 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10751 pr " free (%s);\n" n
10757 (* Check for errors. *)
10758 pr " if (r == %s) {\n" error_code;
10759 pr " throw_exception (env, guestfs_last_error (g));\n";
10760 pr " return %s;\n" no_ret;
10763 (* Return value. *)
10764 (match fst style with
10766 | RInt _ -> pr " return (jint) r;\n"
10767 | RBool _ -> pr " return (jboolean) r;\n"
10768 | RInt64 _ -> pr " return (jlong) r;\n"
10769 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10770 | RConstOptString _ ->
10771 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10773 pr " jr = (*env)->NewStringUTF (env, r);\n";
10777 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10778 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10779 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10780 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10781 pr " for (i = 0; i < r_len; ++i) {\n";
10782 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10783 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10784 pr " free (r[i]);\n";
10788 | RStruct (_, typ) ->
10789 let jtyp = java_name_of_struct typ in
10790 let cols = cols_of_struct typ in
10791 generate_java_struct_return typ jtyp cols
10792 | RStructList (_, typ) ->
10793 let jtyp = java_name_of_struct typ in
10794 let cols = cols_of_struct typ in
10795 generate_java_struct_list_return typ jtyp cols
10798 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10799 pr " return NULL;\n"
10801 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10810 and generate_java_struct_return typ jtyp cols =
10811 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10812 pr " jr = (*env)->AllocObject (env, cl);\n";
10816 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10817 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10820 pr " char s[33];\n";
10821 pr " memcpy (s, r->%s, 32);\n" name;
10822 pr " s[32] = 0;\n";
10823 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10824 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10828 pr " int len = r->%s_len;\n" name;
10829 pr " char s[len+1];\n";
10830 pr " memcpy (s, r->%s, len);\n" name;
10831 pr " s[len] = 0;\n";
10832 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10833 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10835 | name, (FBytes|FUInt64|FInt64) ->
10836 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10837 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10838 | name, (FUInt32|FInt32) ->
10839 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10840 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10841 | name, FOptPercent ->
10842 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10843 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10845 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10846 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10851 and generate_java_struct_list_return typ jtyp cols =
10852 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10853 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10854 pr " for (i = 0; i < r->len; ++i) {\n";
10855 pr " jfl = (*env)->AllocObject (env, cl);\n";
10859 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10860 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10863 pr " char s[33];\n";
10864 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10865 pr " s[32] = 0;\n";
10866 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10867 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10871 pr " int len = r->val[i].%s_len;\n" name;
10872 pr " char s[len+1];\n";
10873 pr " memcpy (s, r->val[i].%s, len);\n" name;
10874 pr " s[len] = 0;\n";
10875 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10876 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10878 | name, (FBytes|FUInt64|FInt64) ->
10879 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10880 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10881 | name, (FUInt32|FInt32) ->
10882 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10883 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10884 | name, FOptPercent ->
10885 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10886 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10888 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10889 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10891 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10893 pr " guestfs_free_%s_list (r);\n" typ;
10896 and generate_java_makefile_inc () =
10897 generate_header HashStyle GPLv2plus;
10899 pr "java_built_sources = \\\n";
10902 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10904 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10906 and generate_haskell_hs () =
10907 generate_header HaskellStyle LGPLv2plus;
10909 (* XXX We only know how to generate partial FFI for Haskell
10910 * at the moment. Please help out!
10912 let can_generate style =
10916 | RInt64 _, _ -> true
10918 | RConstString _, _
10919 | RConstOptString _, _
10925 | RBufferOut _, _ -> false in
10928 {-# INCLUDE <guestfs.h> #-}
10929 {-# LANGUAGE ForeignFunctionInterface #-}
10934 (* List out the names of the actions we want to export. *)
10936 fun (name, style, _, _, _, _, _) ->
10937 if can_generate style then pr ",\n %s" name
10943 -- Unfortunately some symbols duplicate ones already present
10944 -- in Prelude. We don't know which, so we hard-code a list
10946 import Prelude hiding (truncate)
10950 import Foreign.C.Types
10952 import Control.Exception
10953 import Data.Typeable
10955 data GuestfsS = GuestfsS -- represents the opaque C struct
10956 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10957 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10959 -- XXX define properly later XXX
10963 data IntBool = IntBool
10965 data StatVFS = StatVFS
10966 data Hashtable = Hashtable
10968 foreign import ccall unsafe \"guestfs_create\" c_create
10970 foreign import ccall unsafe \"&guestfs_close\" c_close
10971 :: FunPtr (GuestfsP -> IO ())
10972 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10973 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10975 create :: IO GuestfsH
10978 c_set_error_handler p nullPtr nullPtr
10979 h <- newForeignPtr c_close p
10982 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10983 :: GuestfsP -> IO CString
10985 -- last_error :: GuestfsH -> IO (Maybe String)
10986 -- last_error h = do
10987 -- str <- withForeignPtr h (\\p -> c_last_error p)
10988 -- maybePeek peekCString str
10990 last_error :: GuestfsH -> IO (String)
10992 str <- withForeignPtr h (\\p -> c_last_error p)
10993 if (str == nullPtr)
10994 then return \"no error\"
10995 else peekCString str
10999 (* Generate wrappers for each foreign function. *)
11001 fun (name, style, _, _, _, _, _) ->
11002 if can_generate style then (
11003 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
11005 generate_haskell_prototype ~handle:"GuestfsP" style;
11009 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11011 pr "%s %s = do\n" name
11012 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11014 (* Convert pointer arguments using with* functions. *)
11019 | Pathname n | Device n | Dev_or_Path n | String n ->
11020 pr "withCString %s $ \\%s -> " n n
11022 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11023 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11024 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11025 | Bool _ | Int _ | Int64 _ -> ()
11027 (* Convert integer arguments. *)
11031 | Bool n -> sprintf "(fromBool %s)" n
11032 | Int n -> sprintf "(fromIntegral %s)" n
11033 | Int64 n -> sprintf "(fromIntegral %s)" n
11034 | FileIn n | FileOut n
11035 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
11036 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11038 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11039 (String.concat " " ("p" :: args));
11040 (match fst style with
11041 | RErr | RInt _ | RInt64 _ | RBool _ ->
11042 pr " if (r == -1)\n";
11044 pr " err <- last_error h\n";
11046 | RConstString _ | RConstOptString _ | RString _
11047 | RStringList _ | RStruct _
11048 | RStructList _ | RHashtable _ | RBufferOut _ ->
11049 pr " if (r == nullPtr)\n";
11051 pr " err <- last_error h\n";
11054 (match fst style with
11056 pr " else return ()\n"
11058 pr " else return (fromIntegral r)\n"
11060 pr " else return (fromIntegral r)\n"
11062 pr " else return (toBool r)\n"
11064 | RConstOptString _
11071 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11077 and generate_haskell_prototype ~handle ?(hs = false) style =
11078 pr "%s -> " handle;
11079 let string = if hs then "String" else "CString" in
11080 let int = if hs then "Int" else "CInt" in
11081 let bool = if hs then "Bool" else "CInt" in
11082 let int64 = if hs then "Integer" else "Int64" in
11086 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
11088 if hs then pr "String"
11089 else pr "CString -> CInt"
11090 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11091 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11092 | Bool _ -> pr "%s" bool
11093 | Int _ -> pr "%s" int
11094 | Int64 _ -> pr "%s" int
11095 | FileIn _ -> pr "%s" string
11096 | FileOut _ -> pr "%s" string
11101 (match fst style with
11102 | RErr -> if not hs then pr "CInt"
11103 | RInt _ -> pr "%s" int
11104 | RInt64 _ -> pr "%s" int64
11105 | RBool _ -> pr "%s" bool
11106 | RConstString _ -> pr "%s" string
11107 | RConstOptString _ -> pr "Maybe %s" string
11108 | RString _ -> pr "%s" string
11109 | RStringList _ -> pr "[%s]" string
11110 | RStruct (_, typ) ->
11111 let name = java_name_of_struct typ in
11113 | RStructList (_, typ) ->
11114 let name = java_name_of_struct typ in
11116 | RHashtable _ -> pr "Hashtable"
11117 | RBufferOut _ -> pr "%s" string
11121 and generate_csharp () =
11122 generate_header CPlusPlusStyle LGPLv2plus;
11124 (* XXX Make this configurable by the C# assembly users. *)
11125 let library = "libguestfs.so.0" in
11128 // These C# bindings are highly experimental at present.
11130 // Firstly they only work on Linux (ie. Mono). In order to get them
11131 // to work on Windows (ie. .Net) you would need to port the library
11132 // itself to Windows first.
11134 // The second issue is that some calls are known to be incorrect and
11135 // can cause Mono to segfault. Particularly: calls which pass or
11136 // return string[], or return any structure value. This is because
11137 // we haven't worked out the correct way to do this from C#.
11139 // The third issue is that when compiling you get a lot of warnings.
11140 // We are not sure whether the warnings are important or not.
11142 // Fourthly we do not routinely build or test these bindings as part
11143 // of the make && make check cycle, which means that regressions might
11146 // Suggestions and patches are welcome.
11150 // gmcs Libguestfs.cs
11151 // mono Libguestfs.exe
11153 // (You'll probably want to add a Test class / static main function
11154 // otherwise this won't do anything useful).
11158 using System.Runtime.InteropServices;
11159 using System.Runtime.Serialization;
11160 using System.Collections;
11164 class Error : System.ApplicationException
11166 public Error (string message) : base (message) {}
11167 protected Error (SerializationInfo info, StreamingContext context) {}
11174 [DllImport (\"%s\")]
11175 static extern IntPtr guestfs_create ();
11179 _handle = guestfs_create ();
11180 if (_handle == IntPtr.Zero)
11181 throw new Error (\"could not create guestfs handle\");
11184 [DllImport (\"%s\")]
11185 static extern void guestfs_close (IntPtr h);
11189 guestfs_close (_handle);
11192 [DllImport (\"%s\")]
11193 static extern string guestfs_last_error (IntPtr h);
11195 " library library library;
11197 (* Generate C# structure bindings. We prefix struct names with
11198 * underscore because C# cannot have conflicting struct names and
11199 * method names (eg. "class stat" and "stat").
11203 pr " [StructLayout (LayoutKind.Sequential)]\n";
11204 pr " public class _%s {\n" typ;
11207 | name, FChar -> pr " char %s;\n" name
11208 | name, FString -> pr " string %s;\n" name
11210 pr " uint %s_len;\n" name;
11211 pr " string %s;\n" name
11213 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11214 pr " string %s;\n" name
11215 | name, FUInt32 -> pr " uint %s;\n" name
11216 | name, FInt32 -> pr " int %s;\n" name
11217 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
11218 | name, FInt64 -> pr " long %s;\n" name
11219 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
11225 (* Generate C# function bindings. *)
11227 fun (name, style, _, _, _, shortdesc, _) ->
11228 let rec csharp_return_type () =
11229 match fst style with
11231 | RBool n -> "bool"
11233 | RInt64 n -> "long"
11235 | RConstOptString n
11237 | RBufferOut n -> "string"
11238 | RStruct (_,n) -> "_" ^ n
11239 | RHashtable n -> "Hashtable"
11240 | RStringList n -> "string[]"
11241 | RStructList (_,n) -> sprintf "_%s[]" n
11243 and c_return_type () =
11244 match fst style with
11248 | RInt64 _ -> "long"
11250 | RConstOptString _
11252 | RBufferOut _ -> "string"
11253 | RStruct (_,n) -> "_" ^ n
11255 | RStringList _ -> "string[]"
11256 | RStructList (_,n) -> sprintf "_%s[]" n
11258 and c_error_comparison () =
11259 match fst style with
11263 | RInt64 _ -> "== -1"
11265 | RConstOptString _
11271 | RStructList (_,_) -> "== null"
11273 and generate_extern_prototype () =
11274 pr " static extern %s guestfs_%s (IntPtr h"
11275 (c_return_type ()) name;
11278 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11279 | FileIn n | FileOut n
11281 pr ", [In] string %s" n
11282 | StringList n | DeviceList n ->
11283 pr ", [In] string[] %s" n
11293 and generate_public_prototype () =
11294 pr " public %s %s (" (csharp_return_type ()) name;
11295 let comma = ref false in
11297 if !comma then pr ", ";
11302 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11303 | FileIn n | FileOut n
11305 next (); pr "string %s" n
11306 | StringList n | DeviceList n ->
11307 next (); pr "string[] %s" n
11309 next (); pr "bool %s" n
11311 next (); pr "int %s" n
11313 next (); pr "long %s" n
11317 and generate_call () =
11318 pr "guestfs_%s (_handle" name;
11319 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11323 pr " [DllImport (\"%s\")]\n" library;
11324 generate_extern_prototype ();
11326 pr " /// <summary>\n";
11327 pr " /// %s\n" shortdesc;
11328 pr " /// </summary>\n";
11329 generate_public_prototype ();
11331 pr " %s r;\n" (c_return_type ());
11334 pr " if (r %s)\n" (c_error_comparison ());
11335 pr " throw new Error (guestfs_last_error (_handle));\n";
11336 (match fst style with
11339 pr " return r != 0 ? true : false;\n"
11341 pr " Hashtable rr = new Hashtable ();\n";
11342 pr " for (size_t i = 0; i < r.Length; i += 2)\n";
11343 pr " rr.Add (r[i], r[i+1]);\n";
11345 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11346 | RString _ | RBufferOut _ | RStruct _ | RStringList _
11352 ) all_functions_sorted;
11358 and generate_bindtests () =
11359 generate_header CStyle LGPLv2plus;
11363 #include <stdlib.h>
11364 #include <inttypes.h>
11365 #include <string.h>
11367 #include \"guestfs.h\"
11368 #include \"guestfs-internal.h\"
11369 #include \"guestfs-internal-actions.h\"
11370 #include \"guestfs_protocol.h\"
11372 #define error guestfs_error
11373 #define safe_calloc guestfs_safe_calloc
11374 #define safe_malloc guestfs_safe_malloc
11377 print_strings (char *const *argv)
11382 for (argc = 0; argv[argc] != NULL; ++argc) {
11383 if (argc > 0) printf (\", \");
11384 printf (\"\\\"%%s\\\"\", argv[argc]);
11389 /* The test0 function prints its parameters to stdout. */
11393 match test_functions with
11394 | [] -> assert false
11395 | test0 :: tests -> test0, tests in
11398 let (name, style, _, _, _, _, _) = test0 in
11399 generate_prototype ~extern:false ~semicolon:false ~newline:true
11400 ~handle:"g" ~prefix:"guestfs__" name style;
11405 | Device n | Dev_or_Path n
11408 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
11412 pr " for (i = 0; i < %s_size; ++i)\n" n;
11413 pr " printf (\"<%%02x>\", %s[i]);\n" n;
11414 pr " printf (\"\\n\");\n";
11416 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11417 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
11418 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11419 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
11420 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11422 pr " /* Java changes stdout line buffering so we need this: */\n";
11423 pr " fflush (stdout);\n";
11429 fun (name, style, _, _, _, _, _) ->
11430 if String.sub name (String.length name - 3) 3 <> "err" then (
11431 pr "/* Test normal return. */\n";
11432 generate_prototype ~extern:false ~semicolon:false ~newline:true
11433 ~handle:"g" ~prefix:"guestfs__" name style;
11435 (match fst style with
11440 pr " sscanf (val, \"%%d\", &r);\n";
11443 pr " int64_t r;\n";
11444 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
11447 pr " return STREQ (val, \"true\");\n"
11449 | RConstOptString _ ->
11450 (* Can't return the input string here. Return a static
11451 * string so we ensure we get a segfault if the caller
11452 * tries to free it.
11454 pr " return \"static string\";\n"
11456 pr " return strdup (val);\n"
11458 pr " char **strs;\n";
11460 pr " sscanf (val, \"%%d\", &n);\n";
11461 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11462 pr " for (i = 0; i < n; ++i) {\n";
11463 pr " strs[i] = safe_malloc (g, 16);\n";
11464 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
11466 pr " strs[n] = NULL;\n";
11467 pr " return strs;\n"
11468 | RStruct (_, typ) ->
11469 pr " struct guestfs_%s *r;\n" typ;
11470 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11472 | RStructList (_, typ) ->
11473 pr " struct guestfs_%s_list *r;\n" typ;
11474 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11475 pr " sscanf (val, \"%%d\", &r->len);\n";
11476 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11479 pr " char **strs;\n";
11481 pr " sscanf (val, \"%%d\", &n);\n";
11482 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11483 pr " for (i = 0; i < n; ++i) {\n";
11484 pr " strs[i*2] = safe_malloc (g, 16);\n";
11485 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11486 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11487 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11489 pr " strs[n*2] = NULL;\n";
11490 pr " return strs;\n"
11492 pr " return strdup (val);\n"
11497 pr "/* Test error return. */\n";
11498 generate_prototype ~extern:false ~semicolon:false ~newline:true
11499 ~handle:"g" ~prefix:"guestfs__" name style;
11501 pr " error (g, \"error\");\n";
11502 (match fst style with
11503 | RErr | RInt _ | RInt64 _ | RBool _ ->
11505 | RConstString _ | RConstOptString _
11506 | RString _ | RStringList _ | RStruct _
11510 pr " return NULL;\n"
11517 and generate_ocaml_bindtests () =
11518 generate_header OCamlStyle GPLv2plus;
11522 let g = Guestfs.create () in
11526 String.concat " " (
11529 | CallString s -> "\"" ^ s ^ "\""
11530 | CallOptString None -> "None"
11531 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11532 | CallStringList xs ->
11533 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11534 | CallInt i when i >= 0 -> string_of_int i
11535 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11536 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11537 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11538 | CallBool b -> string_of_bool b
11539 | CallBuffer s -> sprintf "%S" s
11544 generate_lang_bindtests (
11545 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11548 pr "print_endline \"EOF\"\n"
11550 and generate_perl_bindtests () =
11551 pr "#!/usr/bin/perl -w\n";
11552 generate_header HashStyle GPLv2plus;
11559 my $g = Sys::Guestfs->new ();
11563 String.concat ", " (
11566 | CallString s -> "\"" ^ s ^ "\""
11567 | CallOptString None -> "undef"
11568 | CallOptString (Some s) -> sprintf "\"%s\"" s
11569 | CallStringList xs ->
11570 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11571 | CallInt i -> string_of_int i
11572 | CallInt64 i -> Int64.to_string i
11573 | CallBool b -> if b then "1" else "0"
11574 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11579 generate_lang_bindtests (
11580 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11583 pr "print \"EOF\\n\"\n"
11585 and generate_python_bindtests () =
11586 generate_header HashStyle GPLv2plus;
11591 g = guestfs.GuestFS ()
11595 String.concat ", " (
11598 | CallString s -> "\"" ^ s ^ "\""
11599 | CallOptString None -> "None"
11600 | CallOptString (Some s) -> sprintf "\"%s\"" s
11601 | CallStringList xs ->
11602 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11603 | CallInt i -> string_of_int i
11604 | CallInt64 i -> Int64.to_string i
11605 | CallBool b -> if b then "1" else "0"
11606 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11611 generate_lang_bindtests (
11612 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11615 pr "print \"EOF\"\n"
11617 and generate_ruby_bindtests () =
11618 generate_header HashStyle GPLv2plus;
11623 g = Guestfs::create()
11627 String.concat ", " (
11630 | CallString s -> "\"" ^ s ^ "\""
11631 | CallOptString None -> "nil"
11632 | CallOptString (Some s) -> sprintf "\"%s\"" s
11633 | CallStringList xs ->
11634 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11635 | CallInt i -> string_of_int i
11636 | CallInt64 i -> Int64.to_string i
11637 | CallBool b -> string_of_bool b
11638 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11643 generate_lang_bindtests (
11644 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11647 pr "print \"EOF\\n\"\n"
11649 and generate_java_bindtests () =
11650 generate_header CStyle GPLv2plus;
11653 import com.redhat.et.libguestfs.*;
11655 public class Bindtests {
11656 public static void main (String[] argv)
11659 GuestFS g = new GuestFS ();
11663 String.concat ", " (
11666 | CallString s -> "\"" ^ s ^ "\""
11667 | CallOptString None -> "null"
11668 | CallOptString (Some s) -> sprintf "\"%s\"" s
11669 | CallStringList xs ->
11671 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11672 | CallInt i -> string_of_int i
11673 | CallInt64 i -> Int64.to_string i
11674 | CallBool b -> string_of_bool b
11676 "new byte[] { " ^ String.concat "," (
11677 map_chars (fun c -> string_of_int (Char.code c)) s
11683 generate_lang_bindtests (
11684 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11688 System.out.println (\"EOF\");
11690 catch (Exception exn) {
11691 System.err.println (exn);
11698 and generate_haskell_bindtests () =
11699 generate_header HaskellStyle GPLv2plus;
11702 module Bindtests where
11703 import qualified Guestfs
11706 g <- Guestfs.create
11710 String.concat " " (
11713 | CallString s -> "\"" ^ s ^ "\""
11714 | CallOptString None -> "Nothing"
11715 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11716 | CallStringList xs ->
11717 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11718 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11719 | CallInt i -> string_of_int i
11720 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11721 | CallInt64 i -> Int64.to_string i
11722 | CallBool true -> "True"
11723 | CallBool false -> "False"
11724 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11729 generate_lang_bindtests (
11730 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11733 pr " putStrLn \"EOF\"\n"
11735 (* Language-independent bindings tests - we do it this way to
11736 * ensure there is parity in testing bindings across all languages.
11738 and generate_lang_bindtests call =
11739 call "test0" [CallString "abc"; CallOptString (Some "def");
11740 CallStringList []; CallBool false;
11741 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11742 CallBuffer "abc\000abc"];
11743 call "test0" [CallString "abc"; CallOptString None;
11744 CallStringList []; CallBool false;
11745 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11746 CallBuffer "abc\000abc"];
11747 call "test0" [CallString ""; CallOptString (Some "def");
11748 CallStringList []; CallBool false;
11749 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11750 CallBuffer "abc\000abc"];
11751 call "test0" [CallString ""; CallOptString (Some "");
11752 CallStringList []; CallBool false;
11753 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11754 CallBuffer "abc\000abc"];
11755 call "test0" [CallString "abc"; CallOptString (Some "def");
11756 CallStringList ["1"]; CallBool false;
11757 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11758 CallBuffer "abc\000abc"];
11759 call "test0" [CallString "abc"; CallOptString (Some "def");
11760 CallStringList ["1"; "2"]; CallBool false;
11761 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11762 CallBuffer "abc\000abc"];
11763 call "test0" [CallString "abc"; CallOptString (Some "def");
11764 CallStringList ["1"]; CallBool true;
11765 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11766 CallBuffer "abc\000abc"];
11767 call "test0" [CallString "abc"; CallOptString (Some "def");
11768 CallStringList ["1"]; CallBool false;
11769 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11770 CallBuffer "abc\000abc"];
11771 call "test0" [CallString "abc"; CallOptString (Some "def");
11772 CallStringList ["1"]; CallBool false;
11773 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11774 CallBuffer "abc\000abc"];
11775 call "test0" [CallString "abc"; CallOptString (Some "def");
11776 CallStringList ["1"]; CallBool false;
11777 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11778 CallBuffer "abc\000abc"];
11779 call "test0" [CallString "abc"; CallOptString (Some "def");
11780 CallStringList ["1"]; CallBool false;
11781 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11782 CallBuffer "abc\000abc"];
11783 call "test0" [CallString "abc"; CallOptString (Some "def");
11784 CallStringList ["1"]; CallBool false;
11785 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11786 CallBuffer "abc\000abc"];
11787 call "test0" [CallString "abc"; CallOptString (Some "def");
11788 CallStringList ["1"]; CallBool false;
11789 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11790 CallBuffer "abc\000abc"]
11792 (* XXX Add here tests of the return and error functions. *)
11794 (* Code to generator bindings for virt-inspector. Currently only
11795 * implemented for OCaml code (for virt-p2v 2.0).
11797 let rng_input = "inspector/virt-inspector.rng"
11799 (* Read the input file and parse it into internal structures. This is
11800 * by no means a complete RELAX NG parser, but is just enough to be
11801 * able to parse the specific input file.
11804 | Element of string * rng list (* <element name=name/> *)
11805 | Attribute of string * rng list (* <attribute name=name/> *)
11806 | Interleave of rng list (* <interleave/> *)
11807 | ZeroOrMore of rng (* <zeroOrMore/> *)
11808 | OneOrMore of rng (* <oneOrMore/> *)
11809 | Optional of rng (* <optional/> *)
11810 | Choice of string list (* <choice><value/>*</choice> *)
11811 | Value of string (* <value>str</value> *)
11812 | Text (* <text/> *)
11814 let rec string_of_rng = function
11815 | Element (name, xs) ->
11816 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11817 | Attribute (name, xs) ->
11818 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11819 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11820 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11821 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11822 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11823 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11824 | Value value -> "Value \"" ^ value ^ "\""
11827 and string_of_rng_list xs =
11828 String.concat ", " (List.map string_of_rng xs)
11830 let rec parse_rng ?defines context = function
11832 | Xml.Element ("element", ["name", name], children) :: rest ->
11833 Element (name, parse_rng ?defines context children)
11834 :: parse_rng ?defines context rest
11835 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11836 Attribute (name, parse_rng ?defines context children)
11837 :: parse_rng ?defines context rest
11838 | Xml.Element ("interleave", [], children) :: rest ->
11839 Interleave (parse_rng ?defines context children)
11840 :: parse_rng ?defines context rest
11841 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11842 let rng = parse_rng ?defines context [child] in
11844 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11846 failwithf "%s: <zeroOrMore> contains more than one child element"
11849 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11850 let rng = parse_rng ?defines context [child] in
11852 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11854 failwithf "%s: <oneOrMore> contains more than one child element"
11857 | Xml.Element ("optional", [], [child]) :: rest ->
11858 let rng = parse_rng ?defines context [child] in
11860 | [child] -> Optional child :: parse_rng ?defines context rest
11862 failwithf "%s: <optional> contains more than one child element"
11865 | Xml.Element ("choice", [], children) :: rest ->
11866 let values = List.map (
11867 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11869 failwithf "%s: can't handle anything except <value> in <choice>"
11873 :: parse_rng ?defines context rest
11874 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11875 Value value :: parse_rng ?defines context rest
11876 | Xml.Element ("text", [], []) :: rest ->
11877 Text :: parse_rng ?defines context rest
11878 | Xml.Element ("ref", ["name", name], []) :: rest ->
11879 (* Look up the reference. Because of limitations in this parser,
11880 * we can't handle arbitrarily nested <ref> yet. You can only
11881 * use <ref> from inside <start>.
11883 (match defines with
11885 failwithf "%s: contains <ref>, but no refs are defined yet" context
11887 let rng = StringMap.find name map in
11888 rng @ parse_rng ?defines context rest
11891 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11894 let xml = Xml.parse_file rng_input in
11896 | Xml.Element ("grammar", _,
11897 Xml.Element ("start", _, gram) :: defines) ->
11898 (* The <define/> elements are referenced in the <start> section,
11899 * so build a map of those first.
11901 let defines = List.fold_left (
11903 function Xml.Element ("define", ["name", name], defn) ->
11904 StringMap.add name defn map
11906 failwithf "%s: expected <define name=name/>" rng_input
11907 ) StringMap.empty defines in
11908 let defines = StringMap.mapi parse_rng defines in
11910 (* Parse the <start> clause, passing the defines. *)
11911 parse_rng ~defines "<start>" gram
11913 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11916 let name_of_field = function
11917 | Element (name, _) | Attribute (name, _)
11918 | ZeroOrMore (Element (name, _))
11919 | OneOrMore (Element (name, _))
11920 | Optional (Element (name, _)) -> name
11921 | Optional (Attribute (name, _)) -> name
11922 | Text -> (* an unnamed field in an element *)
11925 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11927 (* At the moment this function only generates OCaml types. However we
11928 * should parameterize it later so it can generate types/structs in a
11929 * variety of languages.
11931 let generate_types xs =
11932 (* A simple type is one that can be printed out directly, eg.
11933 * "string option". A complex type is one which has a name and has
11934 * to be defined via another toplevel definition, eg. a struct.
11936 * generate_type generates code for either simple or complex types.
11937 * In the simple case, it returns the string ("string option"). In
11938 * the complex case, it returns the name ("mountpoint"). In the
11939 * complex case it has to print out the definition before returning,
11940 * so it should only be called when we are at the beginning of a
11941 * new line (BOL context).
11943 let rec generate_type = function
11944 | Text -> (* string *)
11946 | Choice values -> (* [`val1|`val2|...] *)
11947 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11948 | ZeroOrMore rng -> (* <rng> list *)
11949 let t, is_simple = generate_type rng in
11950 t ^ " list (* 0 or more *)", is_simple
11951 | OneOrMore rng -> (* <rng> list *)
11952 let t, is_simple = generate_type rng in
11953 t ^ " list (* 1 or more *)", is_simple
11954 (* virt-inspector hack: bool *)
11955 | Optional (Attribute (name, [Value "1"])) ->
11957 | Optional rng -> (* <rng> list *)
11958 let t, is_simple = generate_type rng in
11959 t ^ " option", is_simple
11960 (* type name = { fields ... } *)
11961 | Element (name, fields) when is_attrs_interleave fields ->
11962 generate_type_struct name (get_attrs_interleave fields)
11963 | Element (name, [field]) (* type name = field *)
11964 | Attribute (name, [field]) ->
11965 let t, is_simple = generate_type field in
11966 if is_simple then (t, true)
11968 pr "type %s = %s\n" name t;
11971 | Element (name, fields) -> (* type name = { fields ... } *)
11972 generate_type_struct name fields
11974 failwithf "generate_type failed at: %s" (string_of_rng rng)
11976 and is_attrs_interleave = function
11977 | [Interleave _] -> true
11978 | Attribute _ :: fields -> is_attrs_interleave fields
11979 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11982 and get_attrs_interleave = function
11983 | [Interleave fields] -> fields
11984 | ((Attribute _) as field) :: fields
11985 | ((Optional (Attribute _)) as field) :: fields ->
11986 field :: get_attrs_interleave fields
11987 | _ -> assert false
11989 and generate_types xs =
11990 List.iter (fun x -> ignore (generate_type x)) xs
11992 and generate_type_struct name fields =
11993 (* Calculate the types of the fields first. We have to do this
11994 * before printing anything so we are still in BOL context.
11996 let types = List.map fst (List.map generate_type fields) in
11998 (* Special case of a struct containing just a string and another
11999 * field. Turn it into an assoc list.
12002 | ["string"; other] ->
12003 let fname1, fname2 =
12005 | [f1; f2] -> name_of_field f1, name_of_field f2
12006 | _ -> assert false in
12007 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12011 pr "type %s = {\n" name;
12013 fun (field, ftype) ->
12014 let fname = name_of_field field in
12015 pr " %s_%s : %s;\n" name fname ftype
12016 ) (List.combine fields types);
12018 (* Return the name of this type, and
12019 * false because it's not a simple type.
12026 let generate_parsers xs =
12027 (* As for generate_type above, generate_parser makes a parser for
12028 * some type, and returns the name of the parser it has generated.
12029 * Because it (may) need to print something, it should always be
12030 * called in BOL context.
12032 let rec generate_parser = function
12033 | Text -> (* string *)
12034 "string_child_or_empty"
12035 | Choice values -> (* [`val1|`val2|...] *)
12036 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12038 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12039 | ZeroOrMore rng -> (* <rng> list *)
12040 let pa = generate_parser rng in
12041 sprintf "(fun x -> List.map %s (Xml.children x))" pa
12042 | OneOrMore rng -> (* <rng> list *)
12043 let pa = generate_parser rng in
12044 sprintf "(fun x -> List.map %s (Xml.children x))" pa
12045 (* virt-inspector hack: bool *)
12046 | Optional (Attribute (name, [Value "1"])) ->
12047 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12048 | Optional rng -> (* <rng> list *)
12049 let pa = generate_parser rng in
12050 sprintf "(function None -> None | Some x -> Some (%s x))" pa
12051 (* type name = { fields ... } *)
12052 | Element (name, fields) when is_attrs_interleave fields ->
12053 generate_parser_struct name (get_attrs_interleave fields)
12054 | Element (name, [field]) -> (* type name = field *)
12055 let pa = generate_parser field in
12056 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12057 pr "let %s =\n" parser_name;
12059 pr "let parse_%s = %s\n" name parser_name;
12061 | Attribute (name, [field]) ->
12062 let pa = generate_parser field in
12063 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12064 pr "let %s =\n" parser_name;
12066 pr "let parse_%s = %s\n" name parser_name;
12068 | Element (name, fields) -> (* type name = { fields ... } *)
12069 generate_parser_struct name ([], fields)
12071 failwithf "generate_parser failed at: %s" (string_of_rng rng)
12073 and is_attrs_interleave = function
12074 | [Interleave _] -> true
12075 | Attribute _ :: fields -> is_attrs_interleave fields
12076 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12079 and get_attrs_interleave = function
12080 | [Interleave fields] -> [], fields
12081 | ((Attribute _) as field) :: fields
12082 | ((Optional (Attribute _)) as field) :: fields ->
12083 let attrs, interleaves = get_attrs_interleave fields in
12084 (field :: attrs), interleaves
12085 | _ -> assert false
12087 and generate_parsers xs =
12088 List.iter (fun x -> ignore (generate_parser x)) xs
12090 and generate_parser_struct name (attrs, interleaves) =
12091 (* Generate parsers for the fields first. We have to do this
12092 * before printing anything so we are still in BOL context.
12094 let fields = attrs @ interleaves in
12095 let pas = List.map generate_parser fields in
12097 (* Generate an intermediate tuple from all the fields first.
12098 * If the type is just a string + another field, then we will
12099 * return this directly, otherwise it is turned into a record.
12101 * RELAX NG note: This code treats <interleave> and plain lists of
12102 * fields the same. In other words, it doesn't bother enforcing
12103 * any ordering of fields in the XML.
12105 pr "let parse_%s x =\n" name;
12106 pr " let t = (\n ";
12107 let comma = ref false in
12110 if !comma then pr ",\n ";
12113 | Optional (Attribute (fname, [field])), pa ->
12115 | Optional (Element (fname, [field])), pa ->
12116 pr "%s (optional_child %S x)" pa fname
12117 | Attribute (fname, [Text]), _ ->
12118 pr "attribute %S x" fname
12119 | (ZeroOrMore _ | OneOrMore _), pa ->
12124 let fname = name_of_field field in
12125 pr "%s (child %S x)" pa fname
12126 ) (List.combine fields pas);
12130 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12134 pr " (Obj.magic t : %s)\n" name
12138 | (Optional (Attribute (fname, [field])), pa) ->
12139 pr " %s_%s =\n" name fname;
12141 | (Optional (Element (fname, [field])), pa) ->
12142 pr " %s_%s =\n" name fname;
12143 pr " (let x = optional_child %S x in\n" fname;
12146 let fname = name_of_field field in
12147 pr " %s_%s =\n" name fname;
12148 pr " (let x = child %S x in\n" fname;
12150 ) (List.combine fields pas);
12154 sprintf "parse_%s" name
12157 generate_parsers xs
12159 (* Generate ocaml/guestfs_inspector.mli. *)
12160 let generate_ocaml_inspector_mli () =
12161 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12164 (** This is an OCaml language binding to the external [virt-inspector]
12167 For more information, please read the man page [virt-inspector(1)].
12172 generate_types grammar;
12173 pr "(** The nested information returned from the {!inspect} function. *)\n";
12177 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12178 (** To inspect a libvirt domain called [name], pass a singleton
12179 list: [inspect [name]]. When using libvirt only, you may
12180 optionally pass a libvirt URI using [inspect ~connect:uri ...].
12182 To inspect a disk image or images, pass a list of the filenames
12183 of the disk images: [inspect filenames]
12185 This function inspects the given guest or disk images and
12186 returns a list of operating system(s) found and a large amount
12187 of information about them. In the vast majority of cases,
12188 a virtual machine only contains a single operating system.
12190 If the optional [~xml] parameter is given, then this function
12191 skips running the external virt-inspector program and just
12192 parses the given XML directly (which is expected to be XML
12193 produced from a previous run of virt-inspector). The list of
12194 names and connect URI are ignored in this case.
12196 This function can throw a wide variety of exceptions, for example
12197 if the external virt-inspector program cannot be found, or if
12198 it doesn't generate valid XML.
12202 (* Generate ocaml/guestfs_inspector.ml. *)
12203 let generate_ocaml_inspector_ml () =
12204 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12209 generate_types grammar;
12213 (* Misc functions which are used by the parser code below. *)
12214 let first_child = function
12215 | Xml.Element (_, _, c::_) -> c
12216 | Xml.Element (name, _, []) ->
12217 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12218 | Xml.PCData str ->
12219 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12221 let string_child_or_empty = function
12222 | Xml.Element (_, _, [Xml.PCData s]) -> s
12223 | Xml.Element (_, _, []) -> \"\"
12224 | Xml.Element (x, _, _) ->
12225 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12227 | Xml.PCData str ->
12228 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12230 let optional_child name xml =
12231 let children = Xml.children xml in
12233 Some (List.find (function
12234 | Xml.Element (n, _, _) when n = name -> true
12235 | _ -> false) children)
12239 let child name xml =
12240 match optional_child name xml with
12243 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12245 let attribute name xml =
12246 try Xml.attrib xml name
12247 with Xml.No_attribute _ ->
12248 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12252 generate_parsers grammar;
12256 (* Run external virt-inspector, then use parser to parse the XML. *)
12257 let inspect ?connect ?xml names =
12261 if names = [] then invalid_arg \"inspect: no names given\";
12262 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12263 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12265 let cmd = List.map Filename.quote cmd in
12266 let cmd = String.concat \" \" cmd in
12267 let chan = open_process_in cmd in
12268 let xml = Xml.parse_in chan in
12269 (match close_process_in chan with
12271 | WEXITED _ -> failwith \"external virt-inspector command failed\"
12272 | WSIGNALED i | WSTOPPED i ->
12273 failwith (\"external virt-inspector command died or stopped on sig \" ^
12278 Xml.parse_string doc in
12279 parse_operatingsystems xml
12282 and generate_max_proc_nr () =
12283 pr "%d\n" max_proc_nr
12285 let output_to filename k =
12286 let filename_new = filename ^ ".new" in
12287 chan := open_out filename_new;
12290 chan := Pervasives.stdout;
12292 (* Is the new file different from the current file? *)
12293 if Sys.file_exists filename && files_equal filename filename_new then
12294 unlink filename_new (* same, so skip it *)
12296 (* different, overwrite old one *)
12297 (try chmod filename 0o644 with Unix_error _ -> ());
12298 rename filename_new filename;
12299 chmod filename 0o444;
12300 printf "written %s\n%!" filename;
12303 let perror msg = function
12304 | Unix_error (err, _, _) ->
12305 eprintf "%s: %s\n" msg (error_message err)
12307 eprintf "%s: %s\n" msg (Printexc.to_string exn)
12309 (* Main program. *)
12312 try openfile "HACKING" [O_RDWR] 0
12314 | Unix_error (ENOENT, _, _) ->
12316 You are probably running this from the wrong directory.
12317 Run it from the top source directory using the command
12322 perror "open: HACKING" exn;
12325 (* Acquire a lock so parallel builds won't try to run the generator
12326 * twice at the same time. Subsequent builds will wait for the first
12327 * one to finish. Note the lock is released implicitly when the
12330 (try lockf lock_fd F_LOCK 1
12332 perror "lock: HACKING" exn;
12335 check_functions ();
12337 output_to "src/guestfs_protocol.x" generate_xdr;
12338 output_to "src/guestfs-structs.h" generate_structs_h;
12339 output_to "src/guestfs-actions.h" generate_actions_h;
12340 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12341 output_to "src/actions.c" generate_client_actions;
12342 output_to "src/bindtests.c" generate_bindtests;
12343 output_to "src/guestfs-structs.pod" generate_structs_pod;
12344 output_to "src/guestfs-actions.pod" generate_actions_pod;
12345 output_to "src/guestfs-availability.pod" generate_availability_pod;
12346 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12347 output_to "src/libguestfs.syms" generate_linker_script;
12348 output_to "daemon/actions.h" generate_daemon_actions_h;
12349 output_to "daemon/stubs.c" generate_daemon_actions;
12350 output_to "daemon/names.c" generate_daemon_names;
12351 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12352 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12353 output_to "capitests/tests.c" generate_tests;
12354 output_to "fish/cmds.c" generate_fish_cmds;
12355 output_to "fish/completion.c" generate_fish_completion;
12356 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12357 output_to "fish/prepopts.c" generate_fish_prep_options_c;
12358 output_to "fish/prepopts.h" generate_fish_prep_options_h;
12359 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12360 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12361 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12362 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12363 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12364 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12365 output_to "perl/Guestfs.xs" generate_perl_xs;
12366 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12367 output_to "perl/bindtests.pl" generate_perl_bindtests;
12368 output_to "python/guestfs-py.c" generate_python_c;
12369 output_to "python/guestfs.py" generate_python_py;
12370 output_to "python/bindtests.py" generate_python_bindtests;
12371 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12372 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12373 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12377 let cols = cols_of_struct typ in
12378 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12379 output_to filename (generate_java_struct jtyp cols);
12382 output_to "java/Makefile.inc" generate_java_makefile_inc;
12383 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12384 output_to "java/Bindtests.java" generate_java_bindtests;
12385 output_to "haskell/Guestfs.hs" generate_haskell_hs;
12386 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12387 output_to "csharp/Libguestfs.cs" generate_csharp;
12389 (* Always generate this file last, and unconditionally. It's used
12390 * by the Makefile to know when we must re-run the generator.
12392 let chan = open_out "src/stamp-generator" in
12393 fprintf chan "1\n";
12396 printf "generated %d lines of code\n" !lines