3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
168 (* Opaque buffer which can contain arbitrary 8 bit data.
169 * In the C API, this is expressed as <char *, int> pair.
170 * Most other languages have a string type which can contain
171 * ASCII NUL. We use whatever type is appropriate for each
173 * Buffers are limited by the total message size. To transfer
174 * large blocks of data, use FileIn/FileOut parameters instead.
175 * To return an arbitrary buffer, use RBufferOut.
181 | ProtocolLimitWarning (* display warning about protocol size limits *)
182 | DangerWillRobinson (* flags particularly dangerous commands *)
183 | FishAlias of string (* provide an alias for this cmd in guestfish *)
184 | FishAction of string (* call this function in guestfish *)
185 | FishOutput of fish_output_t (* how to display output in guestfish *)
186 | NotInFish (* do not export via guestfish *)
187 | NotInDocs (* do not add this function to documentation *)
188 | DeprecatedBy of string (* function is deprecated, use .. instead *)
189 | Optional of string (* function is part of an optional group *)
192 | FishOutputOctal (* for int return, print in octal *)
193 | FishOutputHexadecimal (* for int return, print in hex *)
195 (* You can supply zero or as many tests as you want per API call.
197 * Note that the test environment has 3 block devices, of size 500MB,
198 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199 * a fourth ISO block device with some known files on it (/dev/sdd).
201 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202 * Number of cylinders was 63 for IDE emulated disks with precisely
203 * the same size. How exactly this is calculated is a mystery.
205 * The ISO block device (/dev/sdd) comes from images/test.iso.
207 * To be able to run the tests in a reasonable amount of time,
208 * the virtual machine and block devices are reused between tests.
209 * So don't try testing kill_subprocess :-x
211 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
213 * Don't assume anything about the previous contents of the block
214 * devices. Use 'Init*' to create some initial scenarios.
216 * You can add a prerequisite clause to any individual test. This
217 * is a run-time check, which, if it fails, causes the test to be
218 * skipped. Useful if testing a command which might not work on
219 * all variations of libguestfs builds. A test that has prerequisite
220 * of 'Always' is run unconditionally.
222 * In addition, packagers can skip individual tests by setting the
223 * environment variables: eg:
224 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
225 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
227 type tests = (test_init * test_prereq * test) list
229 (* Run the command sequence and just expect nothing to fail. *)
232 (* Run the command sequence and expect the output of the final
233 * command to be the string.
235 | TestOutput of seq * string
237 (* Run the command sequence and expect the output of the final
238 * command to be the list of strings.
240 | TestOutputList of seq * string list
242 (* Run the command sequence and expect the output of the final
243 * command to be the list of block devices (could be either
244 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245 * character of each string).
247 | TestOutputListOfDevices of seq * string list
249 (* Run the command sequence and expect the output of the final
250 * command to be the integer.
252 | TestOutputInt of seq * int
254 (* Run the command sequence and expect the output of the final
255 * command to be <op> <int>, eg. ">=", "1".
257 | TestOutputIntOp of seq * string * int
259 (* Run the command sequence and expect the output of the final
260 * command to be a true value (!= 0 or != NULL).
262 | TestOutputTrue of seq
264 (* Run the command sequence and expect the output of the final
265 * command to be a false value (== 0 or == NULL, but not an error).
267 | TestOutputFalse of seq
269 (* Run the command sequence and expect the output of the final
270 * command to be a list of the given length (but don't care about
273 | TestOutputLength of seq * int
275 (* Run the command sequence and expect the output of the final
276 * command to be a buffer (RBufferOut), ie. string + size.
278 | TestOutputBuffer of seq * string
280 (* Run the command sequence and expect the output of the final
281 * command to be a structure.
283 | TestOutputStruct of seq * test_field_compare list
285 (* Run the command sequence and expect the final command (only)
288 | TestLastFail of seq
290 and test_field_compare =
291 | CompareWithInt of string * int
292 | CompareWithIntOp of string * string * int
293 | CompareWithString of string * string
294 | CompareFieldsIntEq of string * string
295 | CompareFieldsStrEq of string * string
297 (* Test prerequisites. *)
299 (* Test always runs. *)
302 (* Test is currently disabled - eg. it fails, or it tests some
303 * unimplemented feature.
307 (* 'string' is some C code (a function body) that should return
308 * true or false. The test will run if the code returns true.
312 (* As for 'If' but the test runs _unless_ the code returns true. *)
315 (* Some initial scenarios for testing. *)
317 (* Do nothing, block devices could contain random stuff including
318 * LVM PVs, and some filesystems might be mounted. This is usually
323 (* Block devices are empty and no filesystems are mounted. *)
326 (* /dev/sda contains a single partition /dev/sda1, with random
327 * content. /dev/sdb and /dev/sdc may have random content.
332 (* /dev/sda contains a single partition /dev/sda1, which is formatted
333 * as ext2, empty [except for lost+found] and mounted on /.
334 * /dev/sdb and /dev/sdc may have random content.
340 * /dev/sda1 (is a PV):
341 * /dev/VG/LV (size 8MB):
342 * formatted as ext2, empty [except for lost+found], mounted on /
343 * /dev/sdb and /dev/sdc may have random content.
347 (* /dev/sdd (the ISO, see images/ directory in source)
352 (* Sequence of commands for testing. *)
354 and cmd = string list
356 (* Note about long descriptions: When referring to another
357 * action, use the format C<guestfs_other> (ie. the full name of
358 * the C function). This will be replaced as appropriate in other
361 * Apart from that, long descriptions are just perldoc paragraphs.
364 (* Generate a random UUID (used in tests). *)
366 let chan = open_process_in "uuidgen" in
367 let uuid = input_line chan in
368 (match close_process_in chan with
371 failwith "uuidgen: process exited with non-zero status"
372 | WSIGNALED _ | WSTOPPED _ ->
373 failwith "uuidgen: process signalled or stopped by signal"
377 (* These test functions are used in the language binding tests. *)
379 let test_all_args = [
382 StringList "strlist";
390 let test_all_rets = [
391 (* except for RErr, which is tested thoroughly elsewhere *)
392 "test0rint", RInt "valout";
393 "test0rint64", RInt64 "valout";
394 "test0rbool", RBool "valout";
395 "test0rconststring", RConstString "valout";
396 "test0rconstoptstring", RConstOptString "valout";
397 "test0rstring", RString "valout";
398 "test0rstringlist", RStringList "valout";
399 "test0rstruct", RStruct ("valout", "lvm_pv");
400 "test0rstructlist", RStructList ("valout", "lvm_pv");
401 "test0rhashtable", RHashtable "valout";
404 let test_functions = [
405 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407 "internal test function - do not use",
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
413 It echos the contents of each parameter to stdout.
415 You probably don't want to call this function.");
419 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421 "internal test function - do not use",
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
427 It converts string C<val> to the return type.
429 You probably don't want to call this function.");
430 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432 "internal test function - do not use",
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
438 This function always returns an error.
440 You probably don't want to call this function.")]
444 (* non_daemon_functions are any functions which don't get processed
445 * in the daemon, eg. functions for setting and getting local
446 * configuration values.
449 let non_daemon_functions = test_functions @ [
450 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
452 "launch the qemu subprocess",
454 Internally libguestfs is implemented by running a virtual machine
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
460 ("wait_ready", (RErr, []), -1, [NotInFish],
462 "wait until the qemu subprocess launches (no op)",
464 This function is a no op.
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete. However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
475 ("kill_subprocess", (RErr, []), -1, [],
477 "kill the qemu subprocess",
479 This kills the qemu subprocess. You should never need to call this.");
481 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483 "add an image to examine or modify",
485 This function adds a virtual machine disk image C<filename> to the
486 guest. The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
490 You don't necessarily need to be root when using libguestfs. However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>. In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
507 Note that this call checks for the existence of C<filename>. This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
510 the general C<guestfs_config> call instead.");
512 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514 "add a CD-ROM disk image to examine",
516 This function adds a virtual CD-ROM disk image to the guest.
518 This is equivalent to the qemu parameter C<-cdrom filename>.
526 This call checks for the existence of C<filename>. This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
529 the general C<guestfs_config> call instead.
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
539 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541 "add a drive in snapshot mode (read-only)",
543 This adds a drive in snapshot mode, making it effectively
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed. We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>. In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
560 C<readonly=on> is only added where qemu supports this option.
562 Note that this call checks for the existence of C<filename>. This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
565 the general C<guestfs_config> call instead.");
567 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569 "add qemu parameters",
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>. Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
576 The first character of C<param> string must be a C<-> (dash).
578 C<value> can be NULL.");
580 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
582 "set the qemu binary",
584 Set the qemu binary that we will use.
586 The default is chosen when the library was compiled by the
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
594 Note that you should call this function as early as possible
595 after creating the handle. This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results. Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
602 ("get_qemu", (RConstString "qemu", []), -1, [],
603 [InitNone, Always, TestRun (
605 "get the qemu binary",
607 Return the current qemu binary.
609 This is always non-NULL. If it wasn't set already, then this will
610 return the default qemu binary name.");
612 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
614 "set the search path",
616 Set the path that libguestfs searches for kernel and initrd.img.
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
621 Setting C<path> to C<NULL> restores the default path.");
623 ("get_path", (RConstString "path", []), -1, [],
624 [InitNone, Always, TestRun (
626 "get the search path",
628 Return the current search path.
630 This is always non-NULL. If it wasn't set already, then this will
631 return the default path.");
633 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635 "add options to kernel command line",
637 This function is used to add additional options to the
638 guest kernel command line.
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
646 ("get_append", (RConstOptString "append", []), -1, [],
647 (* This cannot be tested with the current framework. The
648 * function can return NULL in normal operations, which the
649 * test framework interprets as an error.
652 "get the additional kernel options",
654 Return the additional kernel options which are added to the
655 guest kernel command line.
657 If C<NULL> then no options are added.");
659 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
663 If C<autosync> is true, this enables autosync. Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
671 ("get_autosync", (RBool "autosync", []), -1, [],
672 [InitNone, Always, TestRun (
673 [["get_autosync"]])],
676 Get the autosync flag.");
678 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687 ("get_verbose", (RBool "verbose", []), -1, [],
691 This returns the verbose messages flag.");
693 ("is_ready", (RBool "ready", []), -1, [],
694 [InitNone, Always, TestOutputTrue (
696 "is ready to accept commands",
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
701 For more information on states, see L<guestfs(3)>.");
703 ("is_config", (RBool "config", []), -1, [],
704 [InitNone, Always, TestOutputFalse (
706 "is in configuration state",
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
711 For more information on states, see L<guestfs(3)>.");
713 ("is_launching", (RBool "launching", []), -1, [],
714 [InitNone, Always, TestOutputFalse (
715 [["is_launching"]])],
716 "is launching subprocess",
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
721 For more information on states, see L<guestfs(3)>.");
723 ("is_busy", (RBool "busy", []), -1, [],
724 [InitNone, Always, TestOutputFalse (
726 "is busy processing a command",
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
731 For more information on states, see L<guestfs(3)>.");
733 ("get_state", (RInt "state", []), -1, [],
735 "get the current state",
737 This returns the current state as an opaque integer. This is
738 only useful for printing debug and internal error messages.
740 For more information on states, see L<guestfs(3)>.");
742 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743 [InitNone, Always, TestOutputInt (
744 [["set_memsize"; "500"];
745 ["get_memsize"]], 500)],
746 "set memory allocated to the qemu subprocess",
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess. This only has any effect if called before
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
759 ("get_memsize", (RInt "memsize", []), -1, [],
760 [InitNone, Always, TestOutputIntOp (
761 [["get_memsize"]], ">=", 256)],
762 "get memory allocated to the qemu subprocess",
764 This gets the memory size in megabytes allocated to the
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
774 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775 [InitNone, Always, TestOutputIntOp (
776 [["get_pid"]], ">=", 1)],
777 "get PID of qemu subprocess",
779 Return the process ID of the qemu subprocess. If there is no
780 qemu subprocess, then this will return an error.
782 This is an internal call used for debugging and testing.");
784 ("version", (RStruct ("version", "version"), []), -1, [],
785 [InitNone, Always, TestOutputStruct (
786 [["version"]], [CompareWithInt ("major", 1)])],
787 "get the library version number",
789 Return the libguestfs version number that the program is linked
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against. You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
797 This call was added in version C<1.0.58>. In previous
798 versions of libguestfs there was no way to get the version
799 number. From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
802 The call returns a structure with four elements. The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet. The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
811 I<Note:> Don't use this call to test for availability
812 of features. Distro backports makes this unreliable. Use
813 C<guestfs_available> instead.");
815 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816 [InitNone, Always, TestOutputTrue (
817 [["set_selinux"; "true"];
819 "set SELinux enabled or disabled at appliance boot",
821 This sets the selinux flag that is passed to the appliance
822 at boot time. The default is C<selinux=0> (disabled).
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
830 ("get_selinux", (RBool "selinux", []), -1, [],
832 "get SELinux enabled flag",
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
840 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841 [InitNone, Always, TestOutputFalse (
842 [["set_trace"; "false"];
844 "enable or disable command traces",
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish. In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
860 ("get_trace", (RBool "trace", []), -1, [],
862 "get command trace enabled flag",
864 Return the command trace flag.");
866 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867 [InitNone, Always, TestOutputFalse (
868 [["set_direct"; "false"];
870 "enable or disable direct appliance mode",
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
880 You probably don't want to use this unless you know what you
883 The default is disabled.");
885 ("get_direct", (RBool "direct", []), -1, [],
887 "get direct appliance mode flag",
889 Return the direct appliance mode flag.");
891 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892 [InitNone, Always, TestOutputTrue (
893 [["set_recovery_proc"; "true"];
894 ["get_recovery_proc"]])],
895 "enable or disable the recovery process",
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process. The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself). In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
911 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
913 "get recovery process enabled flag",
915 Return the recovery process enabled flag.");
917 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
919 "add a drive specifying the QEMU block emulation to use",
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
924 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
926 "add a drive read-only specifying the QEMU block emulation to use",
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
933 (* daemon_functions are any functions which cause some action
934 * to take place in the daemon.
937 let daemon_functions = [
938 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939 [InitEmpty, Always, TestOutput (
940 [["part_disk"; "/dev/sda"; "mbr"];
941 ["mkfs"; "ext2"; "/dev/sda1"];
942 ["mount"; "/dev/sda1"; "/"];
943 ["write_file"; "/new"; "new file contents"; "0"];
944 ["cat"; "/new"]], "new file contents")],
945 "mount a guest disk at a position in the filesystem",
947 Mount a guest disk at a position in the filesystem. Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest. If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
953 The rules are the same as for L<mount(2)>: A filesystem must
954 first be mounted on C</> before others can be mounted. Other
955 filesystems can only be mounted on directories which already
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
961 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
964 ("sync", (RErr, []), 2, [],
965 [ InitEmpty, Always, TestRun [["sync"]]],
966 "sync disks, writes are flushed through to the disk image",
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
974 ("touch", (RErr, [Pathname "path"]), 3, [],
975 [InitBasicFS, Always, TestOutputTrue (
977 ["exists"; "/new"]])],
978 "update file timestamps or create a new file",
980 Touch acts like the L<touch(1)> command. It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
984 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985 [InitISOFS, Always, TestOutput (
986 [["cat"; "/known-2"]], "abcdef\n")],
987 "list the contents of a file",
989 Return the contents of the file named C<path>.
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string). For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
996 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997 [], (* XXX Tricky to test because it depends on the exact format
998 * of the 'ls -l' command, which changes between F10 and F11.
1000 "list the files in a directory (long format)",
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1005 This command is mostly useful for interactive sessions. It
1006 is I<not> intended that you try to parse the output string.");
1008 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009 [InitBasicFS, Always, TestOutputList (
1011 ["touch"; "/newer"];
1012 ["touch"; "/newest"];
1013 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014 "list the files in a directory",
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd). The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1020 This command is mostly useful for interactive sessions. Programs
1021 should probably use C<guestfs_readdir> instead.");
1023 ("list_devices", (RStringList "devices", []), 7, [],
1024 [InitEmpty, Always, TestOutputListOfDevices (
1025 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026 "list the block devices",
1028 List all the block devices.
1030 The full block device names are returned, eg. C</dev/sda>");
1032 ("list_partitions", (RStringList "partitions", []), 8, [],
1033 [InitBasicFS, Always, TestOutputListOfDevices (
1034 [["list_partitions"]], ["/dev/sda1"]);
1035 InitEmpty, Always, TestOutputListOfDevices (
1036 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038 "list the partitions",
1040 List all the partitions detected on all block devices.
1042 The full partition device names are returned, eg. C</dev/sda1>
1044 This does not return logical volumes. For that you will need to
1045 call C<guestfs_lvs>.");
1047 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049 [["pvs"]], ["/dev/sda1"]);
1050 InitEmpty, Always, TestOutputListOfDevices (
1051 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052 ["pvcreate"; "/dev/sda1"];
1053 ["pvcreate"; "/dev/sda2"];
1054 ["pvcreate"; "/dev/sda3"];
1055 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056 "list the LVM physical volumes (PVs)",
1058 List all the physical volumes detected. This is the equivalent
1059 of the L<pvs(8)> command.
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1064 See also C<guestfs_pvs_full>.");
1066 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067 [InitBasicFSonLVM, Always, TestOutputList (
1069 InitEmpty, Always, TestOutputList (
1070 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071 ["pvcreate"; "/dev/sda1"];
1072 ["pvcreate"; "/dev/sda2"];
1073 ["pvcreate"; "/dev/sda3"];
1074 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075 ["vgcreate"; "VG2"; "/dev/sda3"];
1076 ["vgs"]], ["VG1"; "VG2"])],
1077 "list the LVM volume groups (VGs)",
1079 List all the volumes groups detected. This is the equivalent
1080 of the L<vgs(8)> command.
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1085 See also C<guestfs_vgs_full>.");
1087 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088 [InitBasicFSonLVM, Always, TestOutputList (
1089 [["lvs"]], ["/dev/VG/LV"]);
1090 InitEmpty, Always, TestOutputList (
1091 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092 ["pvcreate"; "/dev/sda1"];
1093 ["pvcreate"; "/dev/sda2"];
1094 ["pvcreate"; "/dev/sda3"];
1095 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096 ["vgcreate"; "VG2"; "/dev/sda3"];
1097 ["lvcreate"; "LV1"; "VG1"; "50"];
1098 ["lvcreate"; "LV2"; "VG1"; "50"];
1099 ["lvcreate"; "LV3"; "VG2"; "50"];
1100 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101 "list the LVM logical volumes (LVs)",
1103 List all the logical volumes detected. This is the equivalent
1104 of the L<lvs(8)> command.
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1109 See also C<guestfs_lvs_full>.");
1111 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112 [], (* XXX how to test? *)
1113 "list the LVM physical volumes (PVs)",
1115 List all the physical volumes detected. This is the equivalent
1116 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1118 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119 [], (* XXX how to test? *)
1120 "list the LVM volume groups (VGs)",
1122 List all the volumes groups detected. This is the equivalent
1123 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1125 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM logical volumes (LVs)",
1129 List all the logical volumes detected. This is the equivalent
1130 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1132 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133 [InitISOFS, Always, TestOutputList (
1134 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135 InitISOFS, Always, TestOutputList (
1136 [["read_lines"; "/empty"]], [])],
1137 "read file as lines",
1139 Return the contents of the file named C<path>.
1141 The file contents are returned as a list of lines. Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line). For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1149 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150 [], (* XXX Augeas code needs tests. *)
1151 "create a new Augeas handle",
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1157 You must call this before using any other C<guestfs_aug_*>
1160 C<root> is the filesystem root. C<root> must not be NULL,
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1169 =item C<AUG_SAVE_BACKUP> = 1
1171 Keep the original file with a C<.augsave> extension.
1173 =item C<AUG_SAVE_NEWFILE> = 2
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1178 =item C<AUG_TYPE_CHECK> = 4
1180 Typecheck lenses (can be expensive).
1182 =item C<AUG_NO_STDINC> = 8
1184 Do not use standard load path for modules.
1186 =item C<AUG_SAVE_NOOP> = 16
1188 Make save a no-op, just record what would have been changed.
1190 =item C<AUG_NO_LOAD> = 32
1192 Do not load the tree in C<guestfs_aug_init>.
1196 To close the handle, you can call C<guestfs_aug_close>.
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1200 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201 [], (* XXX Augeas code needs tests. *)
1202 "close the current Augeas handle",
1204 Close the current Augeas handle and free up any resources
1205 used by it. After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1209 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210 [], (* XXX Augeas code needs tests. *)
1211 "define an Augeas variable",
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1220 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221 [], (* XXX Augeas code needs tests. *)
1222 "define an Augeas node",
1224 Defines a variable C<name> whose value is the result of
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1235 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236 [], (* XXX Augeas code needs tests. *)
1237 "look up the value of an Augeas path",
1239 Look up the value associated with C<path>. If C<path>
1240 matches exactly one node, the C<value> is returned.");
1242 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243 [], (* XXX Augeas code needs tests. *)
1244 "set Augeas path to value",
1246 Set the value associated with C<path> to C<val>.
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL. Due to an oversight in the libguestfs API
1250 you cannot do that with this call. Instead you must use the
1251 C<guestfs_aug_clear> call.");
1253 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254 [], (* XXX Augeas code needs tests. *)
1255 "insert a sibling Augeas node",
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1265 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266 [], (* XXX Augeas code needs tests. *)
1267 "remove an Augeas path",
1269 Remove C<path> and all of its children.
1271 On success this returns the number of entries which were removed.");
1273 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274 [], (* XXX Augeas code needs tests. *)
1277 Move the node C<src> to C<dest>. C<src> must match exactly
1278 one node. C<dest> is overwritten if it exists.");
1280 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281 [], (* XXX Augeas code needs tests. *)
1282 "return Augeas nodes which match augpath",
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1288 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289 [], (* XXX Augeas code needs tests. *)
1290 "write all pending Augeas changes to disk",
1292 This writes all pending changes to disk.
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1297 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298 [], (* XXX Augeas code needs tests. *)
1299 "load files into the tree",
1301 Load files into the tree.
1303 See C<aug_load> in the Augeas documentation for the full gory
1306 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307 [], (* XXX Augeas code needs tests. *)
1308 "list Augeas nodes under augpath",
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1313 ("rm", (RErr, [Pathname "path"]), 29, [],
1314 [InitBasicFS, Always, TestRun
1317 InitBasicFS, Always, TestLastFail
1319 InitBasicFS, Always, TestLastFail
1324 Remove the single file C<path>.");
1326 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327 [InitBasicFS, Always, TestRun
1330 InitBasicFS, Always, TestLastFail
1331 [["rmdir"; "/new"]];
1332 InitBasicFS, Always, TestLastFail
1334 ["rmdir"; "/new"]]],
1335 "remove a directory",
1337 Remove the single directory C<path>.");
1339 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340 [InitBasicFS, Always, TestOutputFalse
1342 ["mkdir"; "/new/foo"];
1343 ["touch"; "/new/foo/bar"];
1345 ["exists"; "/new"]]],
1346 "remove a file or directory recursively",
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory. This is like the C<rm -rf> shell
1352 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353 [InitBasicFS, Always, TestOutputTrue
1355 ["is_dir"; "/new"]];
1356 InitBasicFS, Always, TestLastFail
1357 [["mkdir"; "/new/foo/bar"]]],
1358 "create a directory",
1360 Create a directory named C<path>.");
1362 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363 [InitBasicFS, Always, TestOutputTrue
1364 [["mkdir_p"; "/new/foo/bar"];
1365 ["is_dir"; "/new/foo/bar"]];
1366 InitBasicFS, Always, TestOutputTrue
1367 [["mkdir_p"; "/new/foo/bar"];
1368 ["is_dir"; "/new/foo"]];
1369 InitBasicFS, Always, TestOutputTrue
1370 [["mkdir_p"; "/new/foo/bar"];
1371 ["is_dir"; "/new"]];
1372 (* Regression tests for RHBZ#503133: *)
1373 InitBasicFS, Always, TestRun
1375 ["mkdir_p"; "/new"]];
1376 InitBasicFS, Always, TestLastFail
1378 ["mkdir_p"; "/new"]]],
1379 "create a directory and parents",
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary. This is like the C<mkdir -p> shell command.");
1384 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385 [], (* XXX Need stat command to test *)
1388 Change the mode (permissions) of C<path> to C<mode>. Only
1389 numeric modes are supported.
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1395 The mode actually set is affected by the umask.");
1397 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398 [], (* XXX Need stat command to test *)
1399 "change file owner and group",
1401 Change the file owner to C<owner> and group to C<group>.
1403 Only numeric uid and gid are supported. If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1407 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408 [InitISOFS, Always, TestOutputTrue (
1409 [["exists"; "/empty"]]);
1410 InitISOFS, Always, TestOutputTrue (
1411 [["exists"; "/directory"]])],
1412 "test if file or directory exists",
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1419 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420 [InitISOFS, Always, TestOutputTrue (
1421 [["is_file"; "/known-1"]]);
1422 InitISOFS, Always, TestOutputFalse (
1423 [["is_file"; "/directory"]])],
1424 "test if file exists",
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name. Note that it returns false for
1428 other objects like directories.
1430 See also C<guestfs_stat>.");
1432 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433 [InitISOFS, Always, TestOutputFalse (
1434 [["is_dir"; "/known-3"]]);
1435 InitISOFS, Always, TestOutputTrue (
1436 [["is_dir"; "/directory"]])],
1437 "test if file exists",
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name. Note that it returns false for
1441 other objects like files.
1443 See also C<guestfs_stat>.");
1445 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446 [InitEmpty, Always, TestOutputListOfDevices (
1447 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448 ["pvcreate"; "/dev/sda1"];
1449 ["pvcreate"; "/dev/sda2"];
1450 ["pvcreate"; "/dev/sda3"];
1451 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452 "create an LVM physical volume",
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1458 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459 [InitEmpty, Always, TestOutputList (
1460 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461 ["pvcreate"; "/dev/sda1"];
1462 ["pvcreate"; "/dev/sda2"];
1463 ["pvcreate"; "/dev/sda3"];
1464 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465 ["vgcreate"; "VG2"; "/dev/sda3"];
1466 ["vgs"]], ["VG1"; "VG2"])],
1467 "create an LVM volume group",
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1472 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473 [InitEmpty, Always, TestOutputList (
1474 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475 ["pvcreate"; "/dev/sda1"];
1476 ["pvcreate"; "/dev/sda2"];
1477 ["pvcreate"; "/dev/sda3"];
1478 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479 ["vgcreate"; "VG2"; "/dev/sda3"];
1480 ["lvcreate"; "LV1"; "VG1"; "50"];
1481 ["lvcreate"; "LV2"; "VG1"; "50"];
1482 ["lvcreate"; "LV3"; "VG2"; "50"];
1483 ["lvcreate"; "LV4"; "VG2"; "50"];
1484 ["lvcreate"; "LV5"; "VG2"; "50"];
1486 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488 "create an LVM logical volume",
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1493 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494 [InitEmpty, Always, TestOutput (
1495 [["part_disk"; "/dev/sda"; "mbr"];
1496 ["mkfs"; "ext2"; "/dev/sda1"];
1497 ["mount_options"; ""; "/dev/sda1"; "/"];
1498 ["write_file"; "/new"; "new file contents"; "0"];
1499 ["cat"; "/new"]], "new file contents")],
1500 "make a filesystem",
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume). The filesystem type is C<fstype>, for
1506 ("sfdisk", (RErr, [Device "device";
1507 Int "cyls"; Int "heads"; Int "sectors";
1508 StringList "lines"]), 43, [DangerWillRobinson],
1510 "create partitions on a block device",
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1515 C<device> should be a block device, for example C</dev/sda>.
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted. Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1525 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1526 information refer to the L<sfdisk(8)> manpage.
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1535 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536 [InitBasicFS, Always, TestOutput (
1537 [["write_file"; "/new"; "new file contents"; "0"];
1538 ["cat"; "/new"]], "new file contents");
1539 InitBasicFS, Always, TestOutput (
1540 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541 ["cat"; "/new"]], "\nnew file contents\n");
1542 InitBasicFS, Always, TestOutput (
1543 [["write_file"; "/new"; "\n\n"; "0"];
1544 ["cat"; "/new"]], "\n\n");
1545 InitBasicFS, Always, TestOutput (
1546 [["write_file"; "/new"; ""; "0"];
1547 ["cat"; "/new"]], "");
1548 InitBasicFS, Always, TestOutput (
1549 [["write_file"; "/new"; "\n\n\n"; "0"];
1550 ["cat"; "/new"]], "\n\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["write_file"; "/new"; "\n"; "0"];
1553 ["cat"; "/new"]], "\n")],
1556 This call creates a file called C<path>. The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version. In the meantime
1567 use C<guestfs_upload>.");
1569 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570 [InitEmpty, Always, TestOutputListOfDevices (
1571 [["part_disk"; "/dev/sda"; "mbr"];
1572 ["mkfs"; "ext2"; "/dev/sda1"];
1573 ["mount_options"; ""; "/dev/sda1"; "/"];
1574 ["mounts"]], ["/dev/sda1"]);
1575 InitEmpty, Always, TestOutputList (
1576 [["part_disk"; "/dev/sda"; "mbr"];
1577 ["mkfs"; "ext2"; "/dev/sda1"];
1578 ["mount_options"; ""; "/dev/sda1"; "/"];
1581 "unmount a filesystem",
1583 This unmounts the given filesystem. The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1587 ("mounts", (RStringList "devices", []), 46, [],
1588 [InitBasicFS, Always, TestOutputListOfDevices (
1589 [["mounts"]], ["/dev/sda1"])],
1590 "show mounted filesystems",
1592 This returns the list of currently mounted filesystems. It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1595 Some internal mounts are not shown.
1597 See also: C<guestfs_mountpoints>");
1599 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600 [InitBasicFS, Always, TestOutputList (
1603 (* check that umount_all can unmount nested mounts correctly: *)
1604 InitEmpty, Always, TestOutputList (
1605 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606 ["mkfs"; "ext2"; "/dev/sda1"];
1607 ["mkfs"; "ext2"; "/dev/sda2"];
1608 ["mkfs"; "ext2"; "/dev/sda3"];
1609 ["mount_options"; ""; "/dev/sda1"; "/"];
1611 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612 ["mkdir"; "/mp1/mp2"];
1613 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614 ["mkdir"; "/mp1/mp2/mp3"];
1617 "unmount all filesystems",
1619 This unmounts all mounted filesystems.
1621 Some internal mounts are not unmounted by this call.");
1623 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1625 "remove all LVM LVs, VGs and PVs",
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1630 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631 [InitISOFS, Always, TestOutput (
1632 [["file"; "/empty"]], "empty");
1633 InitISOFS, Always, TestOutput (
1634 [["file"; "/known-1"]], "ASCII text");
1635 InitISOFS, Always, TestLastFail (
1636 [["file"; "/notexists"]])],
1637 "determine file type",
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file. This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zbsL path>. Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1650 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651 [InitBasicFS, Always, TestOutput (
1652 [["upload"; "test-command"; "/test-command"];
1653 ["chmod"; "0o755"; "/test-command"];
1654 ["command"; "/test-command 1"]], "Result1");
1655 InitBasicFS, Always, TestOutput (
1656 [["upload"; "test-command"; "/test-command"];
1657 ["chmod"; "0o755"; "/test-command"];
1658 ["command"; "/test-command 2"]], "Result2\n");
1659 InitBasicFS, Always, TestOutput (
1660 [["upload"; "test-command"; "/test-command"];
1661 ["chmod"; "0o755"; "/test-command"];
1662 ["command"; "/test-command 3"]], "\nResult3");
1663 InitBasicFS, Always, TestOutput (
1664 [["upload"; "test-command"; "/test-command"];
1665 ["chmod"; "0o755"; "/test-command"];
1666 ["command"; "/test-command 4"]], "\nResult4\n");
1667 InitBasicFS, Always, TestOutput (
1668 [["upload"; "test-command"; "/test-command"];
1669 ["chmod"; "0o755"; "/test-command"];
1670 ["command"; "/test-command 5"]], "\nResult5\n\n");
1671 InitBasicFS, Always, TestOutput (
1672 [["upload"; "test-command"; "/test-command"];
1673 ["chmod"; "0o755"; "/test-command"];
1674 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675 InitBasicFS, Always, TestOutput (
1676 [["upload"; "test-command"; "/test-command"];
1677 ["chmod"; "0o755"; "/test-command"];
1678 ["command"; "/test-command 7"]], "");
1679 InitBasicFS, Always, TestOutput (
1680 [["upload"; "test-command"; "/test-command"];
1681 ["chmod"; "0o755"; "/test-command"];
1682 ["command"; "/test-command 8"]], "\n");
1683 InitBasicFS, Always, TestOutput (
1684 [["upload"; "test-command"; "/test-command"];
1685 ["chmod"; "0o755"; "/test-command"];
1686 ["command"; "/test-command 9"]], "\n\n");
1687 InitBasicFS, Always, TestOutput (
1688 [["upload"; "test-command"; "/test-command"];
1689 ["chmod"; "0o755"; "/test-command"];
1690 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691 InitBasicFS, Always, TestOutput (
1692 [["upload"; "test-command"; "/test-command"];
1693 ["chmod"; "0o755"; "/test-command"];
1694 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695 InitBasicFS, Always, TestLastFail (
1696 [["upload"; "test-command"; "/test-command"];
1697 ["chmod"; "0o755"; "/test-command"];
1698 ["command"; "/test-command"]])],
1699 "run a command from the guest filesystem",
1701 This call runs a command from the guest filesystem. The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters. The list must be
1709 non-empty (ie. must contain a program name). Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1713 The return value is anything printed to I<stdout> by
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message. The error message
1718 string is the content of I<stderr> from the command.
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>. If you require a program from
1722 another location, you should provide the full path in the
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places. It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1731 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732 [InitBasicFS, Always, TestOutputList (
1733 [["upload"; "test-command"; "/test-command"];
1734 ["chmod"; "0o755"; "/test-command"];
1735 ["command_lines"; "/test-command 1"]], ["Result1"]);
1736 InitBasicFS, Always, TestOutputList (
1737 [["upload"; "test-command"; "/test-command"];
1738 ["chmod"; "0o755"; "/test-command"];
1739 ["command_lines"; "/test-command 2"]], ["Result2"]);
1740 InitBasicFS, Always, TestOutputList (
1741 [["upload"; "test-command"; "/test-command"];
1742 ["chmod"; "0o755"; "/test-command"];
1743 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744 InitBasicFS, Always, TestOutputList (
1745 [["upload"; "test-command"; "/test-command"];
1746 ["chmod"; "0o755"; "/test-command"];
1747 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748 InitBasicFS, Always, TestOutputList (
1749 [["upload"; "test-command"; "/test-command"];
1750 ["chmod"; "0o755"; "/test-command"];
1751 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752 InitBasicFS, Always, TestOutputList (
1753 [["upload"; "test-command"; "/test-command"];
1754 ["chmod"; "0o755"; "/test-command"];
1755 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756 InitBasicFS, Always, TestOutputList (
1757 [["upload"; "test-command"; "/test-command"];
1758 ["chmod"; "0o755"; "/test-command"];
1759 ["command_lines"; "/test-command 7"]], []);
1760 InitBasicFS, Always, TestOutputList (
1761 [["upload"; "test-command"; "/test-command"];
1762 ["chmod"; "0o755"; "/test-command"];
1763 ["command_lines"; "/test-command 8"]], [""]);
1764 InitBasicFS, Always, TestOutputList (
1765 [["upload"; "test-command"; "/test-command"];
1766 ["chmod"; "0o755"; "/test-command"];
1767 ["command_lines"; "/test-command 9"]], ["";""]);
1768 InitBasicFS, Always, TestOutputList (
1769 [["upload"; "test-command"; "/test-command"];
1770 ["chmod"; "0o755"; "/test-command"];
1771 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772 InitBasicFS, Always, TestOutputList (
1773 [["upload"; "test-command"; "/test-command"];
1774 ["chmod"; "0o755"; "/test-command"];
1775 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776 "run a command, returning lines",
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1781 See also: C<guestfs_sh_lines>");
1783 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784 [InitISOFS, Always, TestOutputStruct (
1785 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786 "get file information",
1788 Returns file information for the given C<path>.
1790 This is the same as the C<stat(2)> system call.");
1792 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793 [InitISOFS, Always, TestOutputStruct (
1794 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795 "get file information for a symbolic link",
1797 Returns file information for the given C<path>.
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1803 This is the same as the C<lstat(2)> system call.");
1805 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806 [InitISOFS, Always, TestOutputStruct (
1807 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808 "get file system statistics",
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1814 This is the same as the C<statvfs(2)> system call.");
1816 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1818 "get ext2/ext3/ext4 superblock details",
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1823 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1824 manpage for more details. The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1828 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829 [InitEmpty, Always, TestOutputTrue (
1830 [["blockdev_setro"; "/dev/sda"];
1831 ["blockdev_getro"; "/dev/sda"]])],
1832 "set block device to read-only",
1834 Sets the block device named C<device> to read-only.
1836 This uses the L<blockdev(8)> command.");
1838 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839 [InitEmpty, Always, TestOutputFalse (
1840 [["blockdev_setrw"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-write",
1844 Sets the block device named C<device> to read-write.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849 [InitEmpty, Always, TestOutputTrue (
1850 [["blockdev_setro"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "is block device set to read-only",
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1857 This uses the L<blockdev(8)> command.");
1859 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860 [InitEmpty, Always, TestOutputInt (
1861 [["blockdev_getss"; "/dev/sda"]], 512)],
1862 "get sectorsize of block device",
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 This uses the L<blockdev(8)> command.");
1872 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873 [InitEmpty, Always, TestOutputInt (
1874 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875 "get blocksize of block device",
1877 This returns the block size of a device.
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1882 This uses the L<blockdev(8)> command.");
1884 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1886 "set blocksize of block device",
1888 This sets the block size of a device.
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1893 This uses the L<blockdev(8)> command.");
1895 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896 [InitEmpty, Always, TestOutputInt (
1897 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898 "get total size of device in 512-byte sectors",
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1907 This uses the L<blockdev(8)> command.");
1909 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910 [InitEmpty, Always, TestOutputInt (
1911 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912 "get total size of device in bytes",
1914 This returns the size of the device in bytes.
1916 See also C<guestfs_blockdev_getsz>.
1918 This uses the L<blockdev(8)> command.");
1920 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921 [InitEmpty, Always, TestRun
1922 [["blockdev_flushbufs"; "/dev/sda"]]],
1923 "flush device buffers",
1925 This tells the kernel to flush internal buffers associated
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_rereadpt"; "/dev/sda"]]],
1933 "reread partition table",
1935 Reread the partition table on C<device>.
1937 This uses the L<blockdev(8)> command.");
1939 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940 [InitBasicFS, Always, TestOutput (
1941 (* Pick a file from cwd which isn't likely to change. *)
1942 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943 ["checksum"; "md5"; "/COPYING.LIB"]],
1944 Digest.to_hex (Digest.file "COPYING.LIB"))],
1945 "upload a file from the local machine",
1947 Upload local file C<filename> to C<remotefilename> on the
1950 C<filename> can also be a named pipe.
1952 See also C<guestfs_download>.");
1954 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955 [InitBasicFS, Always, TestOutput (
1956 (* Pick a file from cwd which isn't likely to change. *)
1957 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959 ["upload"; "testdownload.tmp"; "/upload"];
1960 ["checksum"; "md5"; "/upload"]],
1961 Digest.to_hex (Digest.file "COPYING.LIB"))],
1962 "download a file to the local machine",
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1967 C<filename> can also be a named pipe.
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1971 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972 [InitISOFS, Always, TestOutput (
1973 [["checksum"; "crc"; "/known-3"]], "2891671662");
1974 InitISOFS, Always, TestLastFail (
1975 [["checksum"; "crc"; "/notexists"]]);
1976 InitISOFS, Always, TestOutput (
1977 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978 InitISOFS, Always, TestOutput (
1979 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980 InitISOFS, Always, TestOutput (
1981 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982 InitISOFS, Always, TestOutput (
1983 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984 InitISOFS, Always, TestOutput (
1985 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988 "compute MD5, SHAx or CRC checksum of file",
1990 This call computes the MD5, SHAx or CRC checksum of the
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2005 Compute the MD5 hash (using the C<md5sum> program).
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2029 The checksum is returned as a printable string.
2031 To get the checksum for a device, use C<guestfs_checksum_device>.
2033 To get the checksums for many files, use C<guestfs_checksums_out>.");
2035 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2036 [InitBasicFS, Always, TestOutput (
2037 [["tar_in"; "../images/helloworld.tar"; "/"];
2038 ["cat"; "/hello"]], "hello\n")],
2039 "unpack tarfile to directory",
2041 This command uploads and unpacks local file C<tarfile> (an
2042 I<uncompressed> tar file) into C<directory>.
2044 To upload a compressed tarball, use C<guestfs_tgz_in>
2045 or C<guestfs_txz_in>.");
2047 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2049 "pack directory into tarfile",
2051 This command packs the contents of C<directory> and downloads
2052 it to local file C<tarfile>.
2054 To download a compressed tarball, use C<guestfs_tgz_out>
2055 or C<guestfs_txz_out>.");
2057 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2058 [InitBasicFS, Always, TestOutput (
2059 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2060 ["cat"; "/hello"]], "hello\n")],
2061 "unpack compressed tarball to directory",
2063 This command uploads and unpacks local file C<tarball> (a
2064 I<gzip compressed> tar file) into C<directory>.
2066 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2068 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2070 "pack directory into compressed tarball",
2072 This command packs the contents of C<directory> and downloads
2073 it to local file C<tarball>.
2075 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2077 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2078 [InitBasicFS, Always, TestLastFail (
2080 ["mount_ro"; "/dev/sda1"; "/"];
2081 ["touch"; "/new"]]);
2082 InitBasicFS, Always, TestOutput (
2083 [["write_file"; "/new"; "data"; "0"];
2085 ["mount_ro"; "/dev/sda1"; "/"];
2086 ["cat"; "/new"]], "data")],
2087 "mount a guest disk, read-only",
2089 This is the same as the C<guestfs_mount> command, but it
2090 mounts the filesystem with the read-only (I<-o ro>) flag.");
2092 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2094 "mount a guest disk with mount options",
2096 This is the same as the C<guestfs_mount> command, but it
2097 allows you to set the mount options as for the
2098 L<mount(8)> I<-o> flag.");
2100 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2102 "mount a guest disk with mount options and vfstype",
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set both the mount options and the vfstype
2106 as for the L<mount(8)> I<-o> and I<-t> flags.");
2108 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2110 "debugging and internals",
2112 The C<guestfs_debug> command exposes some internals of
2113 C<guestfsd> (the guestfs daemon) that runs inside the
2116 There is no comprehensive help for this command. You have
2117 to look at the file C<daemon/debug.c> in the libguestfs source
2118 to find out what you can do.");
2120 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2121 [InitEmpty, Always, TestOutputList (
2122 [["part_disk"; "/dev/sda"; "mbr"];
2123 ["pvcreate"; "/dev/sda1"];
2124 ["vgcreate"; "VG"; "/dev/sda1"];
2125 ["lvcreate"; "LV1"; "VG"; "50"];
2126 ["lvcreate"; "LV2"; "VG"; "50"];
2127 ["lvremove"; "/dev/VG/LV1"];
2128 ["lvs"]], ["/dev/VG/LV2"]);
2129 InitEmpty, Always, TestOutputList (
2130 [["part_disk"; "/dev/sda"; "mbr"];
2131 ["pvcreate"; "/dev/sda1"];
2132 ["vgcreate"; "VG"; "/dev/sda1"];
2133 ["lvcreate"; "LV1"; "VG"; "50"];
2134 ["lvcreate"; "LV2"; "VG"; "50"];
2135 ["lvremove"; "/dev/VG"];
2137 InitEmpty, Always, TestOutputList (
2138 [["part_disk"; "/dev/sda"; "mbr"];
2139 ["pvcreate"; "/dev/sda1"];
2140 ["vgcreate"; "VG"; "/dev/sda1"];
2141 ["lvcreate"; "LV1"; "VG"; "50"];
2142 ["lvcreate"; "LV2"; "VG"; "50"];
2143 ["lvremove"; "/dev/VG"];
2145 "remove an LVM logical volume",
2147 Remove an LVM logical volume C<device>, where C<device> is
2148 the path to the LV, such as C</dev/VG/LV>.
2150 You can also remove all LVs in a volume group by specifying
2151 the VG name, C</dev/VG>.");
2153 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2154 [InitEmpty, Always, TestOutputList (
2155 [["part_disk"; "/dev/sda"; "mbr"];
2156 ["pvcreate"; "/dev/sda1"];
2157 ["vgcreate"; "VG"; "/dev/sda1"];
2158 ["lvcreate"; "LV1"; "VG"; "50"];
2159 ["lvcreate"; "LV2"; "VG"; "50"];
2162 InitEmpty, Always, TestOutputList (
2163 [["part_disk"; "/dev/sda"; "mbr"];
2164 ["pvcreate"; "/dev/sda1"];
2165 ["vgcreate"; "VG"; "/dev/sda1"];
2166 ["lvcreate"; "LV1"; "VG"; "50"];
2167 ["lvcreate"; "LV2"; "VG"; "50"];
2170 "remove an LVM volume group",
2172 Remove an LVM volume group C<vgname>, (for example C<VG>).
2174 This also forcibly removes all logical volumes in the volume
2177 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2178 [InitEmpty, Always, TestOutputListOfDevices (
2179 [["part_disk"; "/dev/sda"; "mbr"];
2180 ["pvcreate"; "/dev/sda1"];
2181 ["vgcreate"; "VG"; "/dev/sda1"];
2182 ["lvcreate"; "LV1"; "VG"; "50"];
2183 ["lvcreate"; "LV2"; "VG"; "50"];
2185 ["pvremove"; "/dev/sda1"];
2187 InitEmpty, Always, TestOutputListOfDevices (
2188 [["part_disk"; "/dev/sda"; "mbr"];
2189 ["pvcreate"; "/dev/sda1"];
2190 ["vgcreate"; "VG"; "/dev/sda1"];
2191 ["lvcreate"; "LV1"; "VG"; "50"];
2192 ["lvcreate"; "LV2"; "VG"; "50"];
2194 ["pvremove"; "/dev/sda1"];
2196 InitEmpty, Always, TestOutputListOfDevices (
2197 [["part_disk"; "/dev/sda"; "mbr"];
2198 ["pvcreate"; "/dev/sda1"];
2199 ["vgcreate"; "VG"; "/dev/sda1"];
2200 ["lvcreate"; "LV1"; "VG"; "50"];
2201 ["lvcreate"; "LV2"; "VG"; "50"];
2203 ["pvremove"; "/dev/sda1"];
2205 "remove an LVM physical volume",
2207 This wipes a physical volume C<device> so that LVM will no longer
2210 The implementation uses the C<pvremove> command which refuses to
2211 wipe physical volumes that contain any volume groups, so you have
2212 to remove those first.");
2214 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2215 [InitBasicFS, Always, TestOutput (
2216 [["set_e2label"; "/dev/sda1"; "testlabel"];
2217 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2218 "set the ext2/3/4 filesystem label",
2220 This sets the ext2/3/4 filesystem label of the filesystem on
2221 C<device> to C<label>. Filesystem labels are limited to
2224 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2225 to return the existing label on a filesystem.");
2227 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2229 "get the ext2/3/4 filesystem label",
2231 This returns the ext2/3/4 filesystem label of the filesystem on
2234 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2235 (let uuid = uuidgen () in
2236 [InitBasicFS, Always, TestOutput (
2237 [["set_e2uuid"; "/dev/sda1"; uuid];
2238 ["get_e2uuid"; "/dev/sda1"]], uuid);
2239 InitBasicFS, Always, TestOutput (
2240 [["set_e2uuid"; "/dev/sda1"; "clear"];
2241 ["get_e2uuid"; "/dev/sda1"]], "");
2242 (* We can't predict what UUIDs will be, so just check the commands run. *)
2243 InitBasicFS, Always, TestRun (
2244 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2245 InitBasicFS, Always, TestRun (
2246 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2247 "set the ext2/3/4 filesystem UUID",
2249 This sets the ext2/3/4 filesystem UUID of the filesystem on
2250 C<device> to C<uuid>. The format of the UUID and alternatives
2251 such as C<clear>, C<random> and C<time> are described in the
2252 L<tune2fs(8)> manpage.
2254 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2255 to return the existing UUID of a filesystem.");
2257 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2259 "get the ext2/3/4 filesystem UUID",
2261 This returns the ext2/3/4 filesystem UUID of the filesystem on
2264 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2265 [InitBasicFS, Always, TestOutputInt (
2266 [["umount"; "/dev/sda1"];
2267 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2268 InitBasicFS, Always, TestOutputInt (
2269 [["umount"; "/dev/sda1"];
2270 ["zero"; "/dev/sda1"];
2271 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2272 "run the filesystem checker",
2274 This runs the filesystem checker (fsck) on C<device> which
2275 should have filesystem type C<fstype>.
2277 The returned integer is the status. See L<fsck(8)> for the
2278 list of status codes from C<fsck>.
2286 Multiple status codes can be summed together.
2290 A non-zero return code can mean \"success\", for example if
2291 errors have been corrected on the filesystem.
2295 Checking or repairing NTFS volumes is not supported
2300 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2302 ("zero", (RErr, [Device "device"]), 85, [],
2303 [InitBasicFS, Always, TestOutput (
2304 [["umount"; "/dev/sda1"];
2305 ["zero"; "/dev/sda1"];
2306 ["file"; "/dev/sda1"]], "data")],
2307 "write zeroes to the device",
2309 This command writes zeroes over the first few blocks of C<device>.
2311 How many blocks are zeroed isn't specified (but it's I<not> enough
2312 to securely wipe the device). It should be sufficient to remove
2313 any partition tables, filesystem superblocks and so on.
2315 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2317 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2318 (* Test disabled because grub-install incompatible with virtio-blk driver.
2319 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2321 [InitBasicFS, Disabled, TestOutputTrue (
2322 [["grub_install"; "/"; "/dev/sda1"];
2323 ["is_dir"; "/boot"]])],
2326 This command installs GRUB (the Grand Unified Bootloader) on
2327 C<device>, with the root directory being C<root>.");
2329 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2330 [InitBasicFS, Always, TestOutput (
2331 [["write_file"; "/old"; "file content"; "0"];
2332 ["cp"; "/old"; "/new"];
2333 ["cat"; "/new"]], "file content");
2334 InitBasicFS, Always, TestOutputTrue (
2335 [["write_file"; "/old"; "file content"; "0"];
2336 ["cp"; "/old"; "/new"];
2337 ["is_file"; "/old"]]);
2338 InitBasicFS, Always, TestOutput (
2339 [["write_file"; "/old"; "file content"; "0"];
2341 ["cp"; "/old"; "/dir/new"];
2342 ["cat"; "/dir/new"]], "file content")],
2345 This copies a file from C<src> to C<dest> where C<dest> is
2346 either a destination filename or destination directory.");
2348 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2349 [InitBasicFS, Always, TestOutput (
2350 [["mkdir"; "/olddir"];
2351 ["mkdir"; "/newdir"];
2352 ["write_file"; "/olddir/file"; "file content"; "0"];
2353 ["cp_a"; "/olddir"; "/newdir"];
2354 ["cat"; "/newdir/olddir/file"]], "file content")],
2355 "copy a file or directory recursively",
2357 This copies a file or directory from C<src> to C<dest>
2358 recursively using the C<cp -a> command.");
2360 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2361 [InitBasicFS, Always, TestOutput (
2362 [["write_file"; "/old"; "file content"; "0"];
2363 ["mv"; "/old"; "/new"];
2364 ["cat"; "/new"]], "file content");
2365 InitBasicFS, Always, TestOutputFalse (
2366 [["write_file"; "/old"; "file content"; "0"];
2367 ["mv"; "/old"; "/new"];
2368 ["is_file"; "/old"]])],
2371 This moves a file from C<src> to C<dest> where C<dest> is
2372 either a destination filename or destination directory.");
2374 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2375 [InitEmpty, Always, TestRun (
2376 [["drop_caches"; "3"]])],
2377 "drop kernel page cache, dentries and inodes",
2379 This instructs the guest kernel to drop its page cache,
2380 and/or dentries and inode caches. The parameter C<whattodrop>
2381 tells the kernel what precisely to drop, see
2382 L<http://linux-mm.org/Drop_Caches>
2384 Setting C<whattodrop> to 3 should drop everything.
2386 This automatically calls L<sync(2)> before the operation,
2387 so that the maximum guest memory is freed.");
2389 ("dmesg", (RString "kmsgs", []), 91, [],
2390 [InitEmpty, Always, TestRun (
2392 "return kernel messages",
2394 This returns the kernel messages (C<dmesg> output) from
2395 the guest kernel. This is sometimes useful for extended
2396 debugging of problems.
2398 Another way to get the same information is to enable
2399 verbose messages with C<guestfs_set_verbose> or by setting
2400 the environment variable C<LIBGUESTFS_DEBUG=1> before
2401 running the program.");
2403 ("ping_daemon", (RErr, []), 92, [],
2404 [InitEmpty, Always, TestRun (
2405 [["ping_daemon"]])],
2406 "ping the guest daemon",
2408 This is a test probe into the guestfs daemon running inside
2409 the qemu subprocess. Calling this function checks that the
2410 daemon responds to the ping message, without affecting the daemon
2411 or attached block device(s) in any other way.");
2413 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2414 [InitBasicFS, Always, TestOutputTrue (
2415 [["write_file"; "/file1"; "contents of a file"; "0"];
2416 ["cp"; "/file1"; "/file2"];
2417 ["equal"; "/file1"; "/file2"]]);
2418 InitBasicFS, Always, TestOutputFalse (
2419 [["write_file"; "/file1"; "contents of a file"; "0"];
2420 ["write_file"; "/file2"; "contents of another file"; "0"];
2421 ["equal"; "/file1"; "/file2"]]);
2422 InitBasicFS, Always, TestLastFail (
2423 [["equal"; "/file1"; "/file2"]])],
2424 "test if two files have equal contents",
2426 This compares the two files C<file1> and C<file2> and returns
2427 true if their content is exactly equal, or false otherwise.
2429 The external L<cmp(1)> program is used for the comparison.");
2431 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2432 [InitISOFS, Always, TestOutputList (
2433 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2434 InitISOFS, Always, TestOutputList (
2435 [["strings"; "/empty"]], [])],
2436 "print the printable strings in a file",
2438 This runs the L<strings(1)> command on a file and returns
2439 the list of printable strings found.");
2441 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2442 [InitISOFS, Always, TestOutputList (
2443 [["strings_e"; "b"; "/known-5"]], []);
2444 InitBasicFS, Disabled, TestOutputList (
2445 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2446 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2447 "print the printable strings in a file",
2449 This is like the C<guestfs_strings> command, but allows you to
2450 specify the encoding.
2452 See the L<strings(1)> manpage for the full list of encodings.
2454 Commonly useful encodings are C<l> (lower case L) which will
2455 show strings inside Windows/x86 files.
2457 The returned strings are transcoded to UTF-8.");
2459 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2460 [InitISOFS, Always, TestOutput (
2461 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2462 (* Test for RHBZ#501888c2 regression which caused large hexdump
2463 * commands to segfault.
2465 InitISOFS, Always, TestRun (
2466 [["hexdump"; "/100krandom"]])],
2467 "dump a file in hexadecimal",
2469 This runs C<hexdump -C> on the given C<path>. The result is
2470 the human-readable, canonical hex dump of the file.");
2472 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2473 [InitNone, Always, TestOutput (
2474 [["part_disk"; "/dev/sda"; "mbr"];
2475 ["mkfs"; "ext3"; "/dev/sda1"];
2476 ["mount_options"; ""; "/dev/sda1"; "/"];
2477 ["write_file"; "/new"; "test file"; "0"];
2478 ["umount"; "/dev/sda1"];
2479 ["zerofree"; "/dev/sda1"];
2480 ["mount_options"; ""; "/dev/sda1"; "/"];
2481 ["cat"; "/new"]], "test file")],
2482 "zero unused inodes and disk blocks on ext2/3 filesystem",
2484 This runs the I<zerofree> program on C<device>. This program
2485 claims to zero unused inodes and disk blocks on an ext2/3
2486 filesystem, thus making it possible to compress the filesystem
2489 You should B<not> run this program if the filesystem is
2492 It is possible that using this program can damage the filesystem
2493 or data on the filesystem.");
2495 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2497 "resize an LVM physical volume",
2499 This resizes (expands or shrinks) an existing LVM physical
2500 volume to match the new size of the underlying device.");
2502 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2503 Int "cyls"; Int "heads"; Int "sectors";
2504 String "line"]), 99, [DangerWillRobinson],
2506 "modify a single partition on a block device",
2508 This runs L<sfdisk(8)> option to modify just the single
2509 partition C<n> (note: C<n> counts from 1).
2511 For other parameters, see C<guestfs_sfdisk>. You should usually
2512 pass C<0> for the cyls/heads/sectors parameters.
2514 See also: C<guestfs_part_add>");
2516 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2518 "display the partition table",
2520 This displays the partition table on C<device>, in the
2521 human-readable output of the L<sfdisk(8)> command. It is
2522 not intended to be parsed.
2524 See also: C<guestfs_part_list>");
2526 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2528 "display the kernel geometry",
2530 This displays the kernel's idea of the geometry of C<device>.
2532 The result is in human-readable format, and not designed to
2535 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2537 "display the disk geometry from the partition table",
2539 This displays the disk geometry of C<device> read from the
2540 partition table. Especially in the case where the underlying
2541 block device has been resized, this can be different from the
2542 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2544 The result is in human-readable format, and not designed to
2547 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2549 "activate or deactivate all volume groups",
2551 This command activates or (if C<activate> is false) deactivates
2552 all logical volumes in all volume groups.
2553 If activated, then they are made known to the
2554 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2555 then those devices disappear.
2557 This command is the same as running C<vgchange -a y|n>");
2559 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2561 "activate or deactivate some volume groups",
2563 This command activates or (if C<activate> is false) deactivates
2564 all logical volumes in the listed volume groups C<volgroups>.
2565 If activated, then they are made known to the
2566 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2567 then those devices disappear.
2569 This command is the same as running C<vgchange -a y|n volgroups...>
2571 Note that if C<volgroups> is an empty list then B<all> volume groups
2572 are activated or deactivated.");
2574 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2575 [InitNone, Always, TestOutput (
2576 [["part_disk"; "/dev/sda"; "mbr"];
2577 ["pvcreate"; "/dev/sda1"];
2578 ["vgcreate"; "VG"; "/dev/sda1"];
2579 ["lvcreate"; "LV"; "VG"; "10"];
2580 ["mkfs"; "ext2"; "/dev/VG/LV"];
2581 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2582 ["write_file"; "/new"; "test content"; "0"];
2584 ["lvresize"; "/dev/VG/LV"; "20"];
2585 ["e2fsck_f"; "/dev/VG/LV"];
2586 ["resize2fs"; "/dev/VG/LV"];
2587 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2588 ["cat"; "/new"]], "test content")],
2589 "resize an LVM logical volume",
2591 This resizes (expands or shrinks) an existing LVM logical
2592 volume to C<mbytes>. When reducing, data in the reduced part
2595 ("resize2fs", (RErr, [Device "device"]), 106, [],
2596 [], (* lvresize tests this *)
2597 "resize an ext2/ext3 filesystem",
2599 This resizes an ext2 or ext3 filesystem to match the size of
2600 the underlying device.
2602 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2603 on the C<device> before calling this command. For unknown reasons
2604 C<resize2fs> sometimes gives an error about this and sometimes not.
2605 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2606 calling this function.");
2608 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2609 [InitBasicFS, Always, TestOutputList (
2610 [["find"; "/"]], ["lost+found"]);
2611 InitBasicFS, Always, TestOutputList (
2615 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2616 InitBasicFS, Always, TestOutputList (
2617 [["mkdir_p"; "/a/b/c"];
2618 ["touch"; "/a/b/c/d"];
2619 ["find"; "/a/b/"]], ["c"; "c/d"])],
2620 "find all files and directories",
2622 This command lists out all files and directories, recursively,
2623 starting at C<directory>. It is essentially equivalent to
2624 running the shell command C<find directory -print> but some
2625 post-processing happens on the output, described below.
2627 This returns a list of strings I<without any prefix>. Thus
2628 if the directory structure was:
2634 then the returned list from C<guestfs_find> C</tmp> would be
2642 If C<directory> is not a directory, then this command returns
2645 The returned list is sorted.
2647 See also C<guestfs_find0>.");
2649 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2650 [], (* lvresize tests this *)
2651 "check an ext2/ext3 filesystem",
2653 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2654 filesystem checker on C<device>, noninteractively (C<-p>),
2655 even if the filesystem appears to be clean (C<-f>).
2657 This command is only needed because of C<guestfs_resize2fs>
2658 (q.v.). Normally you should use C<guestfs_fsck>.");
2660 ("sleep", (RErr, [Int "secs"]), 109, [],
2661 [InitNone, Always, TestRun (
2663 "sleep for some seconds",
2665 Sleep for C<secs> seconds.");
2667 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2668 [InitNone, Always, TestOutputInt (
2669 [["part_disk"; "/dev/sda"; "mbr"];
2670 ["mkfs"; "ntfs"; "/dev/sda1"];
2671 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2672 InitNone, Always, TestOutputInt (
2673 [["part_disk"; "/dev/sda"; "mbr"];
2674 ["mkfs"; "ext2"; "/dev/sda1"];
2675 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2676 "probe NTFS volume",
2678 This command runs the L<ntfs-3g.probe(8)> command which probes
2679 an NTFS C<device> for mountability. (Not all NTFS volumes can
2680 be mounted read-write, and some cannot be mounted at all).
2682 C<rw> is a boolean flag. Set it to true if you want to test
2683 if the volume can be mounted read-write. Set it to false if
2684 you want to test if the volume can be mounted read-only.
2686 The return value is an integer which C<0> if the operation
2687 would succeed, or some non-zero value documented in the
2688 L<ntfs-3g.probe(8)> manual page.");
2690 ("sh", (RString "output", [String "command"]), 111, [],
2691 [], (* XXX needs tests *)
2692 "run a command via the shell",
2694 This call runs a command from the guest filesystem via the
2697 This is like C<guestfs_command>, but passes the command to:
2699 /bin/sh -c \"command\"
2701 Depending on the guest's shell, this usually results in
2702 wildcards being expanded, shell expressions being interpolated
2705 All the provisos about C<guestfs_command> apply to this call.");
2707 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2708 [], (* XXX needs tests *)
2709 "run a command via the shell returning lines",
2711 This is the same as C<guestfs_sh>, but splits the result
2712 into a list of lines.
2714 See also: C<guestfs_command_lines>");
2716 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2717 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2718 * code in stubs.c, since all valid glob patterns must start with "/".
2719 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2721 [InitBasicFS, Always, TestOutputList (
2722 [["mkdir_p"; "/a/b/c"];
2723 ["touch"; "/a/b/c/d"];
2724 ["touch"; "/a/b/c/e"];
2725 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2726 InitBasicFS, Always, TestOutputList (
2727 [["mkdir_p"; "/a/b/c"];
2728 ["touch"; "/a/b/c/d"];
2729 ["touch"; "/a/b/c/e"];
2730 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2731 InitBasicFS, Always, TestOutputList (
2732 [["mkdir_p"; "/a/b/c"];
2733 ["touch"; "/a/b/c/d"];
2734 ["touch"; "/a/b/c/e"];
2735 ["glob_expand"; "/a/*/x/*"]], [])],
2736 "expand a wildcard path",
2738 This command searches for all the pathnames matching
2739 C<pattern> according to the wildcard expansion rules
2742 If no paths match, then this returns an empty list
2743 (note: not an error).
2745 It is just a wrapper around the C L<glob(3)> function
2746 with flags C<GLOB_MARK|GLOB_BRACE>.
2747 See that manual page for more details.");
2749 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2750 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2751 [["scrub_device"; "/dev/sdc"]])],
2752 "scrub (securely wipe) a device",
2754 This command writes patterns over C<device> to make data retrieval
2757 It is an interface to the L<scrub(1)> program. See that
2758 manual page for more details.");
2760 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2761 [InitBasicFS, Always, TestRun (
2762 [["write_file"; "/file"; "content"; "0"];
2763 ["scrub_file"; "/file"]])],
2764 "scrub (securely wipe) a file",
2766 This command writes patterns over a file to make data retrieval
2769 The file is I<removed> after scrubbing.
2771 It is an interface to the L<scrub(1)> program. See that
2772 manual page for more details.");
2774 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2775 [], (* XXX needs testing *)
2776 "scrub (securely wipe) free space",
2778 This command creates the directory C<dir> and then fills it
2779 with files until the filesystem is full, and scrubs the files
2780 as for C<guestfs_scrub_file>, and deletes them.
2781 The intention is to scrub any free space on the partition
2784 It is an interface to the L<scrub(1)> program. See that
2785 manual page for more details.");
2787 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2788 [InitBasicFS, Always, TestRun (
2790 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2791 "create a temporary directory",
2793 This command creates a temporary directory. The
2794 C<template> parameter should be a full pathname for the
2795 temporary directory name with the final six characters being
2798 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2799 the second one being suitable for Windows filesystems.
2801 The name of the temporary directory that was created
2804 The temporary directory is created with mode 0700
2805 and is owned by root.
2807 The caller is responsible for deleting the temporary
2808 directory and its contents after use.
2810 See also: L<mkdtemp(3)>");
2812 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2813 [InitISOFS, Always, TestOutputInt (
2814 [["wc_l"; "/10klines"]], 10000)],
2815 "count lines in a file",
2817 This command counts the lines in a file, using the
2818 C<wc -l> external command.");
2820 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2821 [InitISOFS, Always, TestOutputInt (
2822 [["wc_w"; "/10klines"]], 10000)],
2823 "count words in a file",
2825 This command counts the words in a file, using the
2826 C<wc -w> external command.");
2828 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2829 [InitISOFS, Always, TestOutputInt (
2830 [["wc_c"; "/100kallspaces"]], 102400)],
2831 "count characters in a file",
2833 This command counts the characters in a file, using the
2834 C<wc -c> external command.");
2836 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2837 [InitISOFS, Always, TestOutputList (
2838 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2839 "return first 10 lines of a file",
2841 This command returns up to the first 10 lines of a file as
2842 a list of strings.");
2844 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2845 [InitISOFS, Always, TestOutputList (
2846 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2847 InitISOFS, Always, TestOutputList (
2848 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2849 InitISOFS, Always, TestOutputList (
2850 [["head_n"; "0"; "/10klines"]], [])],
2851 "return first N lines of a file",
2853 If the parameter C<nrlines> is a positive number, this returns the first
2854 C<nrlines> lines of the file C<path>.
2856 If the parameter C<nrlines> is a negative number, this returns lines
2857 from the file C<path>, excluding the last C<nrlines> lines.
2859 If the parameter C<nrlines> is zero, this returns an empty list.");
2861 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2862 [InitISOFS, Always, TestOutputList (
2863 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2864 "return last 10 lines of a file",
2866 This command returns up to the last 10 lines of a file as
2867 a list of strings.");
2869 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2870 [InitISOFS, Always, TestOutputList (
2871 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2872 InitISOFS, Always, TestOutputList (
2873 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2874 InitISOFS, Always, TestOutputList (
2875 [["tail_n"; "0"; "/10klines"]], [])],
2876 "return last N lines of a file",
2878 If the parameter C<nrlines> is a positive number, this returns the last
2879 C<nrlines> lines of the file C<path>.
2881 If the parameter C<nrlines> is a negative number, this returns lines
2882 from the file C<path>, starting with the C<-nrlines>th line.
2884 If the parameter C<nrlines> is zero, this returns an empty list.");
2886 ("df", (RString "output", []), 125, [],
2887 [], (* XXX Tricky to test because it depends on the exact format
2888 * of the 'df' command and other imponderables.
2890 "report file system disk space usage",
2892 This command runs the C<df> command to report disk space used.
2894 This command is mostly useful for interactive sessions. It
2895 is I<not> intended that you try to parse the output string.
2896 Use C<statvfs> from programs.");
2898 ("df_h", (RString "output", []), 126, [],
2899 [], (* XXX Tricky to test because it depends on the exact format
2900 * of the 'df' command and other imponderables.
2902 "report file system disk space usage (human readable)",
2904 This command runs the C<df -h> command to report disk space used
2905 in human-readable format.
2907 This command is mostly useful for interactive sessions. It
2908 is I<not> intended that you try to parse the output string.
2909 Use C<statvfs> from programs.");
2911 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2912 [InitISOFS, Always, TestOutputInt (
2913 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2914 "estimate file space usage",
2916 This command runs the C<du -s> command to estimate file space
2919 C<path> can be a file or a directory. If C<path> is a directory
2920 then the estimate includes the contents of the directory and all
2921 subdirectories (recursively).
2923 The result is the estimated size in I<kilobytes>
2924 (ie. units of 1024 bytes).");
2926 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2927 [InitISOFS, Always, TestOutputList (
2928 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2929 "list files in an initrd",
2931 This command lists out files contained in an initrd.
2933 The files are listed without any initial C</> character. The
2934 files are listed in the order they appear (not necessarily
2935 alphabetical). Directory names are listed as separate items.
2937 Old Linux kernels (2.4 and earlier) used a compressed ext2
2938 filesystem as initrd. We I<only> support the newer initramfs
2939 format (compressed cpio files).");
2941 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2943 "mount a file using the loop device",
2945 This command lets you mount C<file> (a filesystem image
2946 in a file) on a mount point. It is entirely equivalent to
2947 the command C<mount -o loop file mountpoint>.");
2949 ("mkswap", (RErr, [Device "device"]), 130, [],
2950 [InitEmpty, Always, TestRun (
2951 [["part_disk"; "/dev/sda"; "mbr"];
2952 ["mkswap"; "/dev/sda1"]])],
2953 "create a swap partition",
2955 Create a swap partition on C<device>.");
2957 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2958 [InitEmpty, Always, TestRun (
2959 [["part_disk"; "/dev/sda"; "mbr"];
2960 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2961 "create a swap partition with a label",
2963 Create a swap partition on C<device> with label C<label>.
2965 Note that you cannot attach a swap label to a block device
2966 (eg. C</dev/sda>), just to a partition. This appears to be
2967 a limitation of the kernel or swap tools.");
2969 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2970 (let uuid = uuidgen () in
2971 [InitEmpty, Always, TestRun (
2972 [["part_disk"; "/dev/sda"; "mbr"];
2973 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2974 "create a swap partition with an explicit UUID",
2976 Create a swap partition on C<device> with UUID C<uuid>.");
2978 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2979 [InitBasicFS, Always, TestOutputStruct (
2980 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2981 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2982 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2983 InitBasicFS, Always, TestOutputStruct (
2984 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2985 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2986 "make block, character or FIFO devices",
2988 This call creates block or character special devices, or
2989 named pipes (FIFOs).
2991 The C<mode> parameter should be the mode, using the standard
2992 constants. C<devmajor> and C<devminor> are the
2993 device major and minor numbers, only used when creating block
2994 and character special devices.
2996 Note that, just like L<mknod(2)>, the mode must be bitwise
2997 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2998 just creates a regular file). These constants are
2999 available in the standard Linux header files, or you can use
3000 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3001 which are wrappers around this command which bitwise OR
3002 in the appropriate constant for you.
3004 The mode actually set is affected by the umask.");
3006 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3007 [InitBasicFS, Always, TestOutputStruct (
3008 [["mkfifo"; "0o777"; "/node"];
3009 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3010 "make FIFO (named pipe)",
3012 This call creates a FIFO (named pipe) called C<path> with
3013 mode C<mode>. It is just a convenient wrapper around
3016 The mode actually set is affected by the umask.");
3018 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3019 [InitBasicFS, Always, TestOutputStruct (
3020 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3021 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3022 "make block device node",
3024 This call creates a block device node called C<path> with
3025 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3026 It is just a convenient wrapper around C<guestfs_mknod>.
3028 The mode actually set is affected by the umask.");
3030 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3031 [InitBasicFS, Always, TestOutputStruct (
3032 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3033 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3034 "make char device node",
3036 This call creates a char device node called C<path> with
3037 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3038 It is just a convenient wrapper around C<guestfs_mknod>.
3040 The mode actually set is affected by the umask.");
3042 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3043 [InitEmpty, Always, TestOutputInt (
3044 [["umask"; "0o22"]], 0o22)],
3045 "set file mode creation mask (umask)",
3047 This function sets the mask used for creating new files and
3048 device nodes to C<mask & 0777>.
3050 Typical umask values would be C<022> which creates new files
3051 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3052 C<002> which creates new files with permissions like
3053 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3055 The default umask is C<022>. This is important because it
3056 means that directories and device nodes will be created with
3057 C<0644> or C<0755> mode even if you specify C<0777>.
3059 See also C<guestfs_get_umask>,
3060 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3062 This call returns the previous umask.");
3064 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3066 "read directories entries",
3068 This returns the list of directory entries in directory C<dir>.
3070 All entries in the directory are returned, including C<.> and
3071 C<..>. The entries are I<not> sorted, but returned in the same
3072 order as the underlying filesystem.
3074 Also this call returns basic file type information about each
3075 file. The C<ftyp> field will contain one of the following characters:
3113 The L<readdir(3)> returned a C<d_type> field with an
3118 This function is primarily intended for use by programs. To
3119 get a simple list of names, use C<guestfs_ls>. To get a printable
3120 directory for human consumption, use C<guestfs_ll>.");
3122 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3124 "create partitions on a block device",
3126 This is a simplified interface to the C<guestfs_sfdisk>
3127 command, where partition sizes are specified in megabytes
3128 only (rounded to the nearest cylinder) and you don't need
3129 to specify the cyls, heads and sectors parameters which
3130 were rarely if ever used anyway.
3132 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3133 and C<guestfs_part_disk>");
3135 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3137 "determine file type inside a compressed file",
3139 This command runs C<file> after first decompressing C<path>
3142 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3144 Since 1.0.63, use C<guestfs_file> instead which can now
3145 process compressed files.");
3147 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3149 "list extended attributes of a file or directory",
3151 This call lists the extended attributes of the file or directory
3154 At the system call level, this is a combination of the
3155 L<listxattr(2)> and L<getxattr(2)> calls.
3157 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3159 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3161 "list extended attributes of a file or directory",
3163 This is the same as C<guestfs_getxattrs>, but if C<path>
3164 is a symbolic link, then it returns the extended attributes
3165 of the link itself.");
3167 ("setxattr", (RErr, [String "xattr";
3168 String "val"; Int "vallen"; (* will be BufferIn *)
3169 Pathname "path"]), 143, [Optional "linuxxattrs"],
3171 "set extended attribute of a file or directory",
3173 This call sets the extended attribute named C<xattr>
3174 of the file C<path> to the value C<val> (of length C<vallen>).
3175 The value is arbitrary 8 bit data.
3177 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3179 ("lsetxattr", (RErr, [String "xattr";
3180 String "val"; Int "vallen"; (* will be BufferIn *)
3181 Pathname "path"]), 144, [Optional "linuxxattrs"],
3183 "set extended attribute of a file or directory",
3185 This is the same as C<guestfs_setxattr>, but if C<path>
3186 is a symbolic link, then it sets an extended attribute
3187 of the link itself.");
3189 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3191 "remove extended attribute of a file or directory",
3193 This call removes the extended attribute named C<xattr>
3194 of the file C<path>.
3196 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3198 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3200 "remove extended attribute of a file or directory",
3202 This is the same as C<guestfs_removexattr>, but if C<path>
3203 is a symbolic link, then it removes an extended attribute
3204 of the link itself.");
3206 ("mountpoints", (RHashtable "mps", []), 147, [],
3210 This call is similar to C<guestfs_mounts>. That call returns
3211 a list of devices. This one returns a hash table (map) of
3212 device name to directory where the device is mounted.");
3214 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3215 (* This is a special case: while you would expect a parameter
3216 * of type "Pathname", that doesn't work, because it implies
3217 * NEED_ROOT in the generated calling code in stubs.c, and
3218 * this function cannot use NEED_ROOT.
3221 "create a mountpoint",
3223 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3224 specialized calls that can be used to create extra mountpoints
3225 before mounting the first filesystem.
3227 These calls are I<only> necessary in some very limited circumstances,
3228 mainly the case where you want to mount a mix of unrelated and/or
3229 read-only filesystems together.
3231 For example, live CDs often contain a \"Russian doll\" nest of
3232 filesystems, an ISO outer layer, with a squashfs image inside, with
3233 an ext2/3 image inside that. You can unpack this as follows
3236 add-ro Fedora-11-i686-Live.iso
3239 mkmountpoint /squash
3242 mount-loop /cd/LiveOS/squashfs.img /squash
3243 mount-loop /squash/LiveOS/ext3fs.img /ext3
3245 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3247 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3249 "remove a mountpoint",
3251 This calls removes a mountpoint that was previously created
3252 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3253 for full details.");
3255 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3256 [InitISOFS, Always, TestOutputBuffer (
3257 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3260 This calls returns the contents of the file C<path> as a
3263 Unlike C<guestfs_cat>, this function can correctly
3264 handle files that contain embedded ASCII NUL characters.
3265 However unlike C<guestfs_download>, this function is limited
3266 in the total size of file that can be handled.");
3268 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3269 [InitISOFS, Always, TestOutputList (
3270 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3271 InitISOFS, Always, TestOutputList (
3272 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3273 "return lines matching a pattern",
3275 This calls the external C<grep> program and returns the
3278 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3279 [InitISOFS, Always, TestOutputList (
3280 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3281 "return lines matching a pattern",
3283 This calls the external C<egrep> program and returns the
3286 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3287 [InitISOFS, Always, TestOutputList (
3288 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3289 "return lines matching a pattern",
3291 This calls the external C<fgrep> program and returns the
3294 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3295 [InitISOFS, Always, TestOutputList (
3296 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3297 "return lines matching a pattern",
3299 This calls the external C<grep -i> program and returns the
3302 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3303 [InitISOFS, Always, TestOutputList (
3304 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3305 "return lines matching a pattern",
3307 This calls the external C<egrep -i> program and returns the
3310 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3311 [InitISOFS, Always, TestOutputList (
3312 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3313 "return lines matching a pattern",
3315 This calls the external C<fgrep -i> program and returns the
3318 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3319 [InitISOFS, Always, TestOutputList (
3320 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3321 "return lines matching a pattern",
3323 This calls the external C<zgrep> program and returns the
3326 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3327 [InitISOFS, Always, TestOutputList (
3328 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3329 "return lines matching a pattern",
3331 This calls the external C<zegrep> program and returns the
3334 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3335 [InitISOFS, Always, TestOutputList (
3336 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3337 "return lines matching a pattern",
3339 This calls the external C<zfgrep> program and returns the
3342 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3343 [InitISOFS, Always, TestOutputList (
3344 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3345 "return lines matching a pattern",
3347 This calls the external C<zgrep -i> program and returns the
3350 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3351 [InitISOFS, Always, TestOutputList (
3352 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3353 "return lines matching a pattern",
3355 This calls the external C<zegrep -i> program and returns the
3358 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3359 [InitISOFS, Always, TestOutputList (
3360 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3361 "return lines matching a pattern",
3363 This calls the external C<zfgrep -i> program and returns the
3366 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3367 [InitISOFS, Always, TestOutput (
3368 [["realpath"; "/../directory"]], "/directory")],
3369 "canonicalized absolute pathname",
3371 Return the canonicalized absolute pathname of C<path>. The
3372 returned path has no C<.>, C<..> or symbolic link path elements.");
3374 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3375 [InitBasicFS, Always, TestOutputStruct (
3378 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3379 "create a hard link",
3381 This command creates a hard link using the C<ln> command.");
3383 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3384 [InitBasicFS, Always, TestOutputStruct (
3387 ["ln_f"; "/a"; "/b"];
3388 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3389 "create a hard link",
3391 This command creates a hard link using the C<ln -f> command.
3392 The C<-f> option removes the link (C<linkname>) if it exists already.");
3394 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3395 [InitBasicFS, Always, TestOutputStruct (
3397 ["ln_s"; "a"; "/b"];
3398 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3399 "create a symbolic link",
3401 This command creates a symbolic link using the C<ln -s> command.");
3403 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3404 [InitBasicFS, Always, TestOutput (
3405 [["mkdir_p"; "/a/b"];
3406 ["touch"; "/a/b/c"];
3407 ["ln_sf"; "../d"; "/a/b/c"];
3408 ["readlink"; "/a/b/c"]], "../d")],
3409 "create a symbolic link",
3411 This command creates a symbolic link using the C<ln -sf> command,
3412 The C<-f> option removes the link (C<linkname>) if it exists already.");
3414 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3415 [] (* XXX tested above *),
3416 "read the target of a symbolic link",
3418 This command reads the target of a symbolic link.");
3420 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3421 [InitBasicFS, Always, TestOutputStruct (
3422 [["fallocate"; "/a"; "1000000"];
3423 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3424 "preallocate a file in the guest filesystem",
3426 This command preallocates a file (containing zero bytes) named
3427 C<path> of size C<len> bytes. If the file exists already, it
3430 Do not confuse this with the guestfish-specific
3431 C<alloc> command which allocates a file in the host and
3432 attaches it as a device.");
3434 ("swapon_device", (RErr, [Device "device"]), 170, [],
3435 [InitPartition, Always, TestRun (
3436 [["mkswap"; "/dev/sda1"];
3437 ["swapon_device"; "/dev/sda1"];
3438 ["swapoff_device"; "/dev/sda1"]])],
3439 "enable swap on device",
3441 This command enables the libguestfs appliance to use the
3442 swap device or partition named C<device>. The increased
3443 memory is made available for all commands, for example
3444 those run using C<guestfs_command> or C<guestfs_sh>.
3446 Note that you should not swap to existing guest swap
3447 partitions unless you know what you are doing. They may
3448 contain hibernation information, or other information that
3449 the guest doesn't want you to trash. You also risk leaking
3450 information about the host to the guest this way. Instead,
3451 attach a new host device to the guest and swap on that.");
3453 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3454 [], (* XXX tested by swapon_device *)
3455 "disable swap on device",
3457 This command disables the libguestfs appliance swap
3458 device or partition named C<device>.
3459 See C<guestfs_swapon_device>.");
3461 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3462 [InitBasicFS, Always, TestRun (
3463 [["fallocate"; "/swap"; "8388608"];
3464 ["mkswap_file"; "/swap"];
3465 ["swapon_file"; "/swap"];
3466 ["swapoff_file"; "/swap"]])],
3467 "enable swap on file",
3469 This command enables swap to a file.
3470 See C<guestfs_swapon_device> for other notes.");
3472 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3473 [], (* XXX tested by swapon_file *)
3474 "disable swap on file",
3476 This command disables the libguestfs appliance swap on file.");
3478 ("swapon_label", (RErr, [String "label"]), 174, [],
3479 [InitEmpty, Always, TestRun (
3480 [["part_disk"; "/dev/sdb"; "mbr"];
3481 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3482 ["swapon_label"; "swapit"];
3483 ["swapoff_label"; "swapit"];
3484 ["zero"; "/dev/sdb"];
3485 ["blockdev_rereadpt"; "/dev/sdb"]])],
3486 "enable swap on labeled swap partition",
3488 This command enables swap to a labeled swap partition.
3489 See C<guestfs_swapon_device> for other notes.");
3491 ("swapoff_label", (RErr, [String "label"]), 175, [],
3492 [], (* XXX tested by swapon_label *)
3493 "disable swap on labeled swap partition",
3495 This command disables the libguestfs appliance swap on
3496 labeled swap partition.");
3498 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3499 (let uuid = uuidgen () in
3500 [InitEmpty, Always, TestRun (
3501 [["mkswap_U"; uuid; "/dev/sdb"];
3502 ["swapon_uuid"; uuid];
3503 ["swapoff_uuid"; uuid]])]),
3504 "enable swap on swap partition by UUID",
3506 This command enables swap to a swap partition with the given UUID.
3507 See C<guestfs_swapon_device> for other notes.");
3509 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3510 [], (* XXX tested by swapon_uuid *)
3511 "disable swap on swap partition by UUID",
3513 This command disables the libguestfs appliance swap partition
3514 with the given UUID.");
3516 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3517 [InitBasicFS, Always, TestRun (
3518 [["fallocate"; "/swap"; "8388608"];
3519 ["mkswap_file"; "/swap"]])],
3520 "create a swap file",
3524 This command just writes a swap file signature to an existing
3525 file. To create the file itself, use something like C<guestfs_fallocate>.");
3527 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3528 [InitISOFS, Always, TestRun (
3529 [["inotify_init"; "0"]])],
3530 "create an inotify handle",
3532 This command creates a new inotify handle.
3533 The inotify subsystem can be used to notify events which happen to
3534 objects in the guest filesystem.
3536 C<maxevents> is the maximum number of events which will be
3537 queued up between calls to C<guestfs_inotify_read> or
3538 C<guestfs_inotify_files>.
3539 If this is passed as C<0>, then the kernel (or previously set)
3540 default is used. For Linux 2.6.29 the default was 16384 events.
3541 Beyond this limit, the kernel throws away events, but records
3542 the fact that it threw them away by setting a flag
3543 C<IN_Q_OVERFLOW> in the returned structure list (see
3544 C<guestfs_inotify_read>).
3546 Before any events are generated, you have to add some
3547 watches to the internal watch list. See:
3548 C<guestfs_inotify_add_watch>,
3549 C<guestfs_inotify_rm_watch> and
3550 C<guestfs_inotify_watch_all>.
3552 Queued up events should be read periodically by calling
3553 C<guestfs_inotify_read>
3554 (or C<guestfs_inotify_files> which is just a helpful
3555 wrapper around C<guestfs_inotify_read>). If you don't
3556 read the events out often enough then you risk the internal
3559 The handle should be closed after use by calling
3560 C<guestfs_inotify_close>. This also removes any
3561 watches automatically.
3563 See also L<inotify(7)> for an overview of the inotify interface
3564 as exposed by the Linux kernel, which is roughly what we expose
3565 via libguestfs. Note that there is one global inotify handle
3566 per libguestfs instance.");
3568 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3569 [InitBasicFS, Always, TestOutputList (
3570 [["inotify_init"; "0"];
3571 ["inotify_add_watch"; "/"; "1073741823"];
3574 ["inotify_files"]], ["a"; "b"])],
3575 "add an inotify watch",
3577 Watch C<path> for the events listed in C<mask>.
3579 Note that if C<path> is a directory then events within that
3580 directory are watched, but this does I<not> happen recursively
3581 (in subdirectories).
3583 Note for non-C or non-Linux callers: the inotify events are
3584 defined by the Linux kernel ABI and are listed in
3585 C</usr/include/sys/inotify.h>.");
3587 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3589 "remove an inotify watch",
3591 Remove a previously defined inotify watch.
3592 See C<guestfs_inotify_add_watch>.");
3594 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3596 "return list of inotify events",
3598 Return the complete queue of events that have happened
3599 since the previous read call.
3601 If no events have happened, this returns an empty list.
3603 I<Note>: In order to make sure that all events have been
3604 read, you must call this function repeatedly until it
3605 returns an empty list. The reason is that the call will
3606 read events up to the maximum appliance-to-host message
3607 size and leave remaining events in the queue.");
3609 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3611 "return list of watched files that had events",
3613 This function is a helpful wrapper around C<guestfs_inotify_read>
3614 which just returns a list of pathnames of objects that were
3615 touched. The returned pathnames are sorted and deduplicated.");
3617 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3619 "close the inotify handle",
3621 This closes the inotify handle which was previously
3622 opened by inotify_init. It removes all watches, throws
3623 away any pending events, and deallocates all resources.");
3625 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3627 "set SELinux security context",
3629 This sets the SELinux security context of the daemon
3630 to the string C<context>.
3632 See the documentation about SELINUX in L<guestfs(3)>.");
3634 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3636 "get SELinux security context",
3638 This gets the SELinux security context of the daemon.
3640 See the documentation about SELINUX in L<guestfs(3)>,
3641 and C<guestfs_setcon>");
3643 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3644 [InitEmpty, Always, TestOutput (
3645 [["part_disk"; "/dev/sda"; "mbr"];
3646 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3647 ["mount_options"; ""; "/dev/sda1"; "/"];
3648 ["write_file"; "/new"; "new file contents"; "0"];
3649 ["cat"; "/new"]], "new file contents")],
3650 "make a filesystem with block size",
3652 This call is similar to C<guestfs_mkfs>, but it allows you to
3653 control the block size of the resulting filesystem. Supported
3654 block sizes depend on the filesystem type, but typically they
3655 are C<1024>, C<2048> or C<4096> only.");
3657 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3658 [InitEmpty, Always, TestOutput (
3659 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3660 ["mke2journal"; "4096"; "/dev/sda1"];
3661 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3662 ["mount_options"; ""; "/dev/sda2"; "/"];
3663 ["write_file"; "/new"; "new file contents"; "0"];
3664 ["cat"; "/new"]], "new file contents")],
3665 "make ext2/3/4 external journal",
3667 This creates an ext2 external journal on C<device>. It is equivalent
3670 mke2fs -O journal_dev -b blocksize device");
3672 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3673 [InitEmpty, Always, TestOutput (
3674 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3675 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3676 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3677 ["mount_options"; ""; "/dev/sda2"; "/"];
3678 ["write_file"; "/new"; "new file contents"; "0"];
3679 ["cat"; "/new"]], "new file contents")],
3680 "make ext2/3/4 external journal with label",
3682 This creates an ext2 external journal on C<device> with label C<label>.");
3684 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3685 (let uuid = uuidgen () in
3686 [InitEmpty, Always, TestOutput (
3687 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3688 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3689 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3690 ["mount_options"; ""; "/dev/sda2"; "/"];
3691 ["write_file"; "/new"; "new file contents"; "0"];
3692 ["cat"; "/new"]], "new file contents")]),
3693 "make ext2/3/4 external journal with UUID",
3695 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3697 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3699 "make ext2/3/4 filesystem with external journal",
3701 This creates an ext2/3/4 filesystem on C<device> with
3702 an external journal on C<journal>. It is equivalent
3705 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3707 See also C<guestfs_mke2journal>.");
3709 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3711 "make ext2/3/4 filesystem with external journal",
3713 This creates an ext2/3/4 filesystem on C<device> with
3714 an external journal on the journal labeled C<label>.
3716 See also C<guestfs_mke2journal_L>.");
3718 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3720 "make ext2/3/4 filesystem with external journal",
3722 This creates an ext2/3/4 filesystem on C<device> with
3723 an external journal on the journal with UUID C<uuid>.
3725 See also C<guestfs_mke2journal_U>.");
3727 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3728 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3729 "load a kernel module",
3731 This loads a kernel module in the appliance.
3733 The kernel module must have been whitelisted when libguestfs
3734 was built (see C<appliance/kmod.whitelist.in> in the source).");
3736 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3737 [InitNone, Always, TestOutput (
3738 [["echo_daemon"; "This is a test"]], "This is a test"
3740 "echo arguments back to the client",
3742 This command concatenate the list of C<words> passed with single spaces between
3743 them and returns the resulting string.
3745 You can use this command to test the connection through to the daemon.
3747 See also C<guestfs_ping_daemon>.");
3749 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3750 [], (* There is a regression test for this. *)
3751 "find all files and directories, returning NUL-separated list",
3753 This command lists out all files and directories, recursively,
3754 starting at C<directory>, placing the resulting list in the
3755 external file called C<files>.
3757 This command works the same way as C<guestfs_find> with the
3758 following exceptions:
3764 The resulting list is written to an external file.
3768 Items (filenames) in the result are separated
3769 by C<\\0> characters. See L<find(1)> option I<-print0>.
3773 This command is not limited in the number of names that it
3778 The result list is not sorted.
3782 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3783 [InitISOFS, Always, TestOutput (
3784 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3785 InitISOFS, Always, TestOutput (
3786 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3787 InitISOFS, Always, TestOutput (
3788 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3789 InitISOFS, Always, TestLastFail (
3790 [["case_sensitive_path"; "/Known-1/"]]);
3791 InitBasicFS, Always, TestOutput (
3793 ["mkdir"; "/a/bbb"];
3794 ["touch"; "/a/bbb/c"];
3795 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3796 InitBasicFS, Always, TestOutput (
3798 ["mkdir"; "/a/bbb"];
3799 ["touch"; "/a/bbb/c"];
3800 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3801 InitBasicFS, Always, TestLastFail (
3803 ["mkdir"; "/a/bbb"];
3804 ["touch"; "/a/bbb/c"];
3805 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3806 "return true path on case-insensitive filesystem",
3808 This can be used to resolve case insensitive paths on
3809 a filesystem which is case sensitive. The use case is
3810 to resolve paths which you have read from Windows configuration
3811 files or the Windows Registry, to the true path.
3813 The command handles a peculiarity of the Linux ntfs-3g
3814 filesystem driver (and probably others), which is that although
3815 the underlying filesystem is case-insensitive, the driver
3816 exports the filesystem to Linux as case-sensitive.
3818 One consequence of this is that special directories such
3819 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3820 (or other things) depending on the precise details of how
3821 they were created. In Windows itself this would not be
3824 Bug or feature? You decide:
3825 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3827 This function resolves the true case of each element in the
3828 path and returns the case-sensitive path.
3830 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3831 might return C<\"/WINDOWS/system32\"> (the exact return value
3832 would depend on details of how the directories were originally
3833 created under Windows).
3836 This function does not handle drive names, backslashes etc.
3838 See also C<guestfs_realpath>.");
3840 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3841 [InitBasicFS, Always, TestOutput (
3842 [["vfs_type"; "/dev/sda1"]], "ext2")],
3843 "get the Linux VFS type corresponding to a mounted device",
3845 This command gets the block device type corresponding to
3846 a mounted device called C<device>.
3848 Usually the result is the name of the Linux VFS module that
3849 is used to mount this device (probably determined automatically
3850 if you used the C<guestfs_mount> call).");
3852 ("truncate", (RErr, [Pathname "path"]), 199, [],
3853 [InitBasicFS, Always, TestOutputStruct (
3854 [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3855 ["truncate"; "/test"];
3856 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3857 "truncate a file to zero size",
3859 This command truncates C<path> to a zero-length file. The
3860 file must exist already.");
3862 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3863 [InitBasicFS, Always, TestOutputStruct (
3864 [["touch"; "/test"];
3865 ["truncate_size"; "/test"; "1000"];
3866 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3867 "truncate a file to a particular size",
3869 This command truncates C<path> to size C<size> bytes. The file
3870 must exist already. If the file is smaller than C<size> then
3871 the file is extended to the required size with null bytes.");
3873 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3874 [InitBasicFS, Always, TestOutputStruct (
3875 [["touch"; "/test"];
3876 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3877 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3878 "set timestamp of a file with nanosecond precision",
3880 This command sets the timestamps of a file with nanosecond
3883 C<atsecs, atnsecs> are the last access time (atime) in secs and
3884 nanoseconds from the epoch.
3886 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3887 secs and nanoseconds from the epoch.
3889 If the C<*nsecs> field contains the special value C<-1> then
3890 the corresponding timestamp is set to the current time. (The
3891 C<*secs> field is ignored in this case).
3893 If the C<*nsecs> field contains the special value C<-2> then
3894 the corresponding timestamp is left unchanged. (The
3895 C<*secs> field is ignored in this case).");
3897 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3898 [InitBasicFS, Always, TestOutputStruct (
3899 [["mkdir_mode"; "/test"; "0o111"];
3900 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3901 "create a directory with a particular mode",
3903 This command creates a directory, setting the initial permissions
3904 of the directory to C<mode>.
3906 For common Linux filesystems, the actual mode which is set will
3907 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
3908 interpret the mode in other ways.
3910 See also C<guestfs_mkdir>, C<guestfs_umask>");
3912 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3914 "change file owner and group",
3916 Change the file owner to C<owner> and group to C<group>.
3917 This is like C<guestfs_chown> but if C<path> is a symlink then
3918 the link itself is changed, not the target.
3920 Only numeric uid and gid are supported. If you want to use
3921 names, you will need to locate and parse the password file
3922 yourself (Augeas support makes this relatively easy).");
3924 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3926 "lstat on multiple files",
3928 This call allows you to perform the C<guestfs_lstat> operation
3929 on multiple files, where all files are in the directory C<path>.
3930 C<names> is the list of files from this directory.
3932 On return you get a list of stat structs, with a one-to-one
3933 correspondence to the C<names> list. If any name did not exist
3934 or could not be lstat'd, then the C<ino> field of that structure
3937 This call is intended for programs that want to efficiently
3938 list a directory contents without making many round-trips.
3939 See also C<guestfs_lxattrlist> for a similarly efficient call
3940 for getting extended attributes. Very long directory listings
3941 might cause the protocol message size to be exceeded, causing
3942 this call to fail. The caller must split up such requests
3943 into smaller groups of names.");
3945 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3947 "lgetxattr on multiple files",
3949 This call allows you to get the extended attributes
3950 of multiple files, where all files are in the directory C<path>.
3951 C<names> is the list of files from this directory.
3953 On return you get a flat list of xattr structs which must be
3954 interpreted sequentially. The first xattr struct always has a zero-length
3955 C<attrname>. C<attrval> in this struct is zero-length
3956 to indicate there was an error doing C<lgetxattr> for this
3957 file, I<or> is a C string which is a decimal number
3958 (the number of following attributes for this file, which could
3959 be C<\"0\">). Then after the first xattr struct are the
3960 zero or more attributes for the first named file.
3961 This repeats for the second and subsequent files.
3963 This call is intended for programs that want to efficiently
3964 list a directory contents without making many round-trips.
3965 See also C<guestfs_lstatlist> for a similarly efficient call
3966 for getting standard stats. Very long directory listings
3967 might cause the protocol message size to be exceeded, causing
3968 this call to fail. The caller must split up such requests
3969 into smaller groups of names.");
3971 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3973 "readlink on multiple files",
3975 This call allows you to do a C<readlink> operation
3976 on multiple files, where all files are in the directory C<path>.
3977 C<names> is the list of files from this directory.
3979 On return you get a list of strings, with a one-to-one
3980 correspondence to the C<names> list. Each string is the
3981 value of the symbol link.
3983 If the C<readlink(2)> operation fails on any name, then
3984 the corresponding result string is the empty string C<\"\">.
3985 However the whole operation is completed even if there
3986 were C<readlink(2)> errors, and so you can call this
3987 function with names where you don't know if they are
3988 symbolic links already (albeit slightly less efficient).
3990 This call is intended for programs that want to efficiently
3991 list a directory contents without making many round-trips.
3992 Very long directory listings might cause the protocol
3993 message size to be exceeded, causing
3994 this call to fail. The caller must split up such requests
3995 into smaller groups of names.");
3997 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3998 [InitISOFS, Always, TestOutputBuffer (
3999 [["pread"; "/known-4"; "1"; "3"]], "\n");
4000 InitISOFS, Always, TestOutputBuffer (
4001 [["pread"; "/empty"; "0"; "100"]], "")],
4002 "read part of a file",
4004 This command lets you read part of a file. It reads C<count>
4005 bytes of the file, starting at C<offset>, from file C<path>.
4007 This may read fewer bytes than requested. For further details
4008 see the L<pread(2)> system call.");
4010 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4011 [InitEmpty, Always, TestRun (
4012 [["part_init"; "/dev/sda"; "gpt"]])],
4013 "create an empty partition table",
4015 This creates an empty partition table on C<device> of one of the
4016 partition types listed below. Usually C<parttype> should be
4017 either C<msdos> or C<gpt> (for large disks).
4019 Initially there are no partitions. Following this, you should
4020 call C<guestfs_part_add> for each partition required.
4022 Possible values for C<parttype> are:
4026 =item B<efi> | B<gpt>
4028 Intel EFI / GPT partition table.
4030 This is recommended for >= 2 TB partitions that will be accessed
4031 from Linux and Intel-based Mac OS X. It also has limited backwards
4032 compatibility with the C<mbr> format.
4034 =item B<mbr> | B<msdos>
4036 The standard PC \"Master Boot Record\" (MBR) format used
4037 by MS-DOS and Windows. This partition type will B<only> work
4038 for device sizes up to 2 TB. For large disks we recommend
4043 Other partition table types that may work but are not
4052 =item B<amiga> | B<rdb>
4054 Amiga \"Rigid Disk Block\" format.
4062 DASD, used on IBM mainframes.
4070 Old Mac partition format. Modern Macs use C<gpt>.
4074 NEC PC-98 format, common in Japan apparently.
4082 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4083 [InitEmpty, Always, TestRun (
4084 [["part_init"; "/dev/sda"; "mbr"];
4085 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4086 InitEmpty, Always, TestRun (
4087 [["part_init"; "/dev/sda"; "gpt"];
4088 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4089 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4090 InitEmpty, Always, TestRun (
4091 [["part_init"; "/dev/sda"; "mbr"];
4092 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4093 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4094 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4095 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4096 "add a partition to the device",
4098 This command adds a partition to C<device>. If there is no partition
4099 table on the device, call C<guestfs_part_init> first.
4101 The C<prlogex> parameter is the type of partition. Normally you
4102 should pass C<p> or C<primary> here, but MBR partition tables also
4103 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4106 C<startsect> and C<endsect> are the start and end of the partition
4107 in I<sectors>. C<endsect> may be negative, which means it counts
4108 backwards from the end of the disk (C<-1> is the last sector).
4110 Creating a partition which covers the whole disk is not so easy.
4111 Use C<guestfs_part_disk> to do that.");
4113 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4114 [InitEmpty, Always, TestRun (
4115 [["part_disk"; "/dev/sda"; "mbr"]]);
4116 InitEmpty, Always, TestRun (
4117 [["part_disk"; "/dev/sda"; "gpt"]])],
4118 "partition whole disk with a single primary partition",
4120 This command is simply a combination of C<guestfs_part_init>
4121 followed by C<guestfs_part_add> to create a single primary partition
4122 covering the whole disk.
4124 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4125 but other possible values are described in C<guestfs_part_init>.");
4127 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4128 [InitEmpty, Always, TestRun (
4129 [["part_disk"; "/dev/sda"; "mbr"];
4130 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4131 "make a partition bootable",
4133 This sets the bootable flag on partition numbered C<partnum> on
4134 device C<device>. Note that partitions are numbered from 1.
4136 The bootable flag is used by some operating systems (notably
4137 Windows) to determine which partition to boot from. It is by
4138 no means universally recognized.");
4140 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4141 [InitEmpty, Always, TestRun (
4142 [["part_disk"; "/dev/sda"; "gpt"];
4143 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4144 "set partition name",
4146 This sets the partition name on partition numbered C<partnum> on
4147 device C<device>. Note that partitions are numbered from 1.
4149 The partition name can only be set on certain types of partition
4150 table. This works on C<gpt> but not on C<mbr> partitions.");
4152 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4153 [], (* XXX Add a regression test for this. *)
4154 "list partitions on a device",
4156 This command parses the partition table on C<device> and
4157 returns the list of partitions found.
4159 The fields in the returned structure are:
4165 Partition number, counting from 1.
4169 Start of the partition I<in bytes>. To get sectors you have to
4170 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4174 End of the partition in bytes.
4178 Size of the partition in bytes.
4182 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4183 [InitEmpty, Always, TestOutput (
4184 [["part_disk"; "/dev/sda"; "gpt"];
4185 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4186 "get the partition table type",
4188 This command examines the partition table on C<device> and
4189 returns the partition table type (format) being used.
4191 Common return values include: C<msdos> (a DOS/Windows style MBR
4192 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4193 values are possible, although unusual. See C<guestfs_part_init>
4196 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4197 [InitBasicFS, Always, TestOutputBuffer (
4198 [["fill"; "0x63"; "10"; "/test"];
4199 ["read_file"; "/test"]], "cccccccccc")],
4200 "fill a file with octets",
4202 This command creates a new file called C<path>. The initial
4203 content of the file is C<len> octets of C<c>, where C<c>
4204 must be a number in the range C<[0..255]>.
4206 To fill a file with zero bytes (sparsely), it is
4207 much more efficient to use C<guestfs_truncate_size>.");
4209 ("available", (RErr, [StringList "groups"]), 216, [],
4210 [InitNone, Always, TestRun [["available"; ""]]],
4211 "test availability of some parts of the API",
4213 This command is used to check the availability of some
4214 groups of functionality in the appliance, which not all builds of
4215 the libguestfs appliance will be able to provide.
4217 The libguestfs groups, and the functions that those
4218 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4220 The argument C<groups> is a list of group names, eg:
4221 C<[\"inotify\", \"augeas\"]> would check for the availability of
4222 the Linux inotify functions and Augeas (configuration file
4225 The command returns no error if I<all> requested groups are available.
4227 It fails with an error if one or more of the requested
4228 groups is unavailable in the appliance.
4230 If an unknown group name is included in the
4231 list of groups then an error is always returned.
4239 You must call C<guestfs_launch> before calling this function.
4241 The reason is because we don't know what groups are
4242 supported by the appliance/daemon until it is running and can
4247 If a group of functions is available, this does not necessarily
4248 mean that they will work. You still have to check for errors
4249 when calling individual API functions even if they are
4254 It is usually the job of distro packagers to build
4255 complete functionality into the libguestfs appliance.
4256 Upstream libguestfs, if built from source with all
4257 requirements satisfied, will support everything.
4261 This call was added in version C<1.0.80>. In previous
4262 versions of libguestfs all you could do would be to speculatively
4263 execute a command to find out if the daemon implemented it.
4264 See also C<guestfs_version>.
4268 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4269 [InitBasicFS, Always, TestOutputBuffer (
4270 [["write_file"; "/src"; "hello, world"; "0"];
4271 ["dd"; "/src"; "/dest"];
4272 ["read_file"; "/dest"]], "hello, world")],
4273 "copy from source to destination using dd",
4275 This command copies from one source device or file C<src>
4276 to another destination device or file C<dest>. Normally you
4277 would use this to copy to or from a device or partition, for
4278 example to duplicate a filesystem.
4280 If the destination is a device, it must be as large or larger
4281 than the source file or device, otherwise the copy will fail.
4282 This command cannot do partial copies (see C<guestfs_copy_size>).");
4284 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4285 [InitBasicFS, Always, TestOutputInt (
4286 [["write_file"; "/file"; "hello, world"; "0"];
4287 ["filesize"; "/file"]], 12)],
4288 "return the size of the file in bytes",
4290 This command returns the size of C<file> in bytes.
4292 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4293 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4294 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4296 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4297 [InitBasicFSonLVM, Always, TestOutputList (
4298 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4299 ["lvs"]], ["/dev/VG/LV2"])],
4300 "rename an LVM logical volume",
4302 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4304 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4305 [InitBasicFSonLVM, Always, TestOutputList (
4307 ["vg_activate"; "false"; "VG"];
4308 ["vgrename"; "VG"; "VG2"];
4309 ["vg_activate"; "true"; "VG2"];
4310 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4311 ["vgs"]], ["VG2"])],
4312 "rename an LVM volume group",
4314 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4316 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4317 [InitISOFS, Always, TestOutputBuffer (
4318 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4319 "list the contents of a single file in an initrd",
4321 This command unpacks the file C<filename> from the initrd file
4322 called C<initrdpath>. The filename must be given I<without> the
4323 initial C</> character.
4325 For example, in guestfish you could use the following command
4326 to examine the boot script (usually called C</init>)
4327 contained in a Linux initrd or initramfs image:
4329 initrd-cat /boot/initrd-<version>.img init
4331 See also C<guestfs_initrd_list>.");
4333 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4335 "get the UUID of a physical volume",
4337 This command returns the UUID of the LVM PV C<device>.");
4339 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4341 "get the UUID of a volume group",
4343 This command returns the UUID of the LVM VG named C<vgname>.");
4345 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4347 "get the UUID of a logical volume",
4349 This command returns the UUID of the LVM LV C<device>.");
4351 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4353 "get the PV UUIDs containing the volume group",
4355 Given a VG called C<vgname>, this returns the UUIDs of all
4356 the physical volumes that this volume group resides on.
4358 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4359 calls to associate physical volumes and volume groups.
4361 See also C<guestfs_vglvuuids>.");
4363 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4365 "get the LV UUIDs of all LVs in the volume group",
4367 Given a VG called C<vgname>, this returns the UUIDs of all
4368 the logical volumes created in this volume group.
4370 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4371 calls to associate logical volumes and volume groups.
4373 See also C<guestfs_vgpvuuids>.");
4375 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4376 [InitBasicFS, Always, TestOutputBuffer (
4377 [["write_file"; "/src"; "hello, world"; "0"];
4378 ["copy_size"; "/src"; "/dest"; "5"];
4379 ["read_file"; "/dest"]], "hello")],
4380 "copy size bytes from source to destination using dd",
4382 This command copies exactly C<size> bytes from one source device
4383 or file C<src> to another destination device or file C<dest>.
4385 Note this will fail if the source is too short or if the destination
4386 is not large enough.");
4388 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4389 [InitBasicFSonLVM, Always, TestRun (
4390 [["zero_device"; "/dev/VG/LV"]])],
4391 "write zeroes to an entire device",
4393 This command writes zeroes over the entire C<device>. Compare
4394 with C<guestfs_zero> which just zeroes the first few blocks of
4397 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4398 [InitBasicFS, Always, TestOutput (
4399 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4400 ["cat"; "/hello"]], "hello\n")],
4401 "unpack compressed tarball to directory",
4403 This command uploads and unpacks local file C<tarball> (an
4404 I<xz compressed> tar file) into C<directory>.");
4406 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4408 "pack directory into compressed tarball",
4410 This command packs the contents of C<directory> and downloads
4411 it to local file C<tarball> (as an xz compressed tar archive).");
4413 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4415 "resize an NTFS filesystem",
4417 This command resizes an NTFS filesystem, expanding or
4418 shrinking it to the size of the underlying device.
4419 See also L<ntfsresize(8)>.");
4421 ("vgscan", (RErr, []), 232, [],
4422 [InitEmpty, Always, TestRun (
4424 "rescan for LVM physical volumes, volume groups and logical volumes",
4426 This rescans all block devices and rebuilds the list of LVM
4427 physical volumes, volume groups and logical volumes.");
4429 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4430 [InitEmpty, Always, TestRun (
4431 [["part_init"; "/dev/sda"; "mbr"];
4432 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4433 ["part_del"; "/dev/sda"; "1"]])],
4434 "delete a partition",
4436 This command deletes the partition numbered C<partnum> on C<device>.
4438 Note that in the case of MBR partitioning, deleting an
4439 extended partition also deletes any logical partitions
4442 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4443 [InitEmpty, Always, TestOutputTrue (
4444 [["part_init"; "/dev/sda"; "mbr"];
4445 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4446 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4447 ["part_get_bootable"; "/dev/sda"; "1"]])],
4448 "return true if a partition is bootable",
4450 This command returns true if the partition C<partnum> on
4451 C<device> has the bootable flag set.
4453 See also C<guestfs_part_set_bootable>.");
4455 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4456 [InitEmpty, Always, TestOutputInt (
4457 [["part_init"; "/dev/sda"; "mbr"];
4458 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4459 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4460 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4461 "get the MBR type byte (ID byte) from a partition",
4463 Returns the MBR type byte (also known as the ID byte) from
4464 the numbered partition C<partnum>.
4466 Note that only MBR (old DOS-style) partitions have type bytes.
4467 You will get undefined results for other partition table
4468 types (see C<guestfs_part_get_parttype>).");
4470 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4471 [], (* tested by part_get_mbr_id *)
4472 "set the MBR type byte (ID byte) of a partition",
4474 Sets the MBR type byte (also known as the ID byte) of
4475 the numbered partition C<partnum> to C<idbyte>. Note
4476 that the type bytes quoted in most documentation are
4477 in fact hexadecimal numbers, but usually documented
4478 without any leading \"0x\" which might be confusing.
4480 Note that only MBR (old DOS-style) partitions have type bytes.
4481 You will get undefined results for other partition table
4482 types (see C<guestfs_part_get_parttype>).");
4484 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4485 [InitISOFS, Always, TestOutput (
4486 [["checksum_device"; "md5"; "/dev/sdd"]],
4487 (Digest.to_hex (Digest.file "images/test.iso")))],
4488 "compute MD5, SHAx or CRC checksum of the contents of a device",
4490 This call computes the MD5, SHAx or CRC checksum of the
4491 contents of the device named C<device>. For the types of
4492 checksums supported see the C<guestfs_checksum> command.");
4494 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4495 [InitNone, Always, TestRun (
4496 [["part_disk"; "/dev/sda"; "mbr"];
4497 ["pvcreate"; "/dev/sda1"];
4498 ["vgcreate"; "VG"; "/dev/sda1"];
4499 ["lvcreate"; "LV"; "VG"; "10"];
4500 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4501 "expand an LV to fill free space",
4503 This expands an existing logical volume C<lv> so that it fills
4504 C<pc>% of the remaining free space in the volume group. Commonly
4505 you would call this with pc = 100 which expands the logical volume
4506 as much as possible, using all remaining free space in the volume
4509 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4510 [], (* XXX Augeas code needs tests. *)
4511 "clear Augeas path",
4513 Set the value associated with C<path> to C<NULL>. This
4514 is the same as the L<augtool(1)> C<clear> command.");
4516 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4517 [InitEmpty, Always, TestOutputInt (
4518 [["get_umask"]], 0o22)],
4519 "get the current umask",
4521 Return the current umask. By default the umask is C<022>
4522 unless it has been set by calling C<guestfs_umask>.");
4524 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4526 "upload a file to the appliance (internal use only)",
4528 The C<guestfs_debug_upload> command uploads a file to
4529 the libguestfs appliance.
4531 There is no comprehensive help for this command. You have
4532 to look at the file C<daemon/debug.c> in the libguestfs source
4533 to find out what it is for.");
4535 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4536 [InitBasicFS, Always, TestOutput (
4537 [["base64_in"; "../images/hello.b64"; "/hello"];
4538 ["cat"; "/hello"]], "hello\n")],
4539 "upload base64-encoded data to file",
4541 This command uploads base64-encoded data from C<base64file>
4544 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4546 "download file and encode as base64",
4548 This command downloads the contents of C<filename>, writing
4549 it out to local file C<base64file> encoded as base64.");
4551 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4553 "compute MD5, SHAx or CRC checksum of files in a directory",
4555 This command computes the checksums of all regular files in
4556 C<directory> and then emits a list of those checksums to
4557 the local output file C<sumsfile>.
4559 This can be used for verifying the integrity of a virtual
4560 machine. However to be properly secure you should pay
4561 attention to the output of the checksum command (it uses
4562 the ones from GNU coreutils). In particular when the
4563 filename is not printable, coreutils uses a special
4564 backslash syntax. For more information, see the GNU
4565 coreutils info file.");
4569 let all_functions = non_daemon_functions @ daemon_functions
4571 (* In some places we want the functions to be displayed sorted
4572 * alphabetically, so this is useful:
4574 let all_functions_sorted =
4575 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4576 compare n1 n2) all_functions
4578 (* Field types for structures. *)
4580 | FChar (* C 'char' (really, a 7 bit byte). *)
4581 | FString (* nul-terminated ASCII string, NOT NULL. *)
4582 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4587 | FBytes (* Any int measure that counts bytes. *)
4588 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4589 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4591 (* Because we generate extra parsing code for LVM command line tools,
4592 * we have to pull out the LVM columns separately here.
4602 "pv_attr", FString (* XXX *);
4603 "pv_pe_count", FInt64;
4604 "pv_pe_alloc_count", FInt64;
4607 "pv_mda_count", FInt64;
4608 "pv_mda_free", FBytes;
4609 (* Not in Fedora 10:
4610 "pv_mda_size", FBytes;
4617 "vg_attr", FString (* XXX *);
4620 "vg_sysid", FString;
4621 "vg_extent_size", FBytes;
4622 "vg_extent_count", FInt64;
4623 "vg_free_count", FInt64;
4628 "snap_count", FInt64;
4631 "vg_mda_count", FInt64;
4632 "vg_mda_free", FBytes;
4633 (* Not in Fedora 10:
4634 "vg_mda_size", FBytes;
4640 "lv_attr", FString (* XXX *);
4643 "lv_kernel_major", FInt64;
4644 "lv_kernel_minor", FInt64;
4646 "seg_count", FInt64;
4648 "snap_percent", FOptPercent;
4649 "copy_percent", FOptPercent;
4652 "mirror_log", FString;
4656 (* Names and fields in all structures (in RStruct and RStructList)
4660 (* The old RIntBool return type, only ever used for aug_defnode. Do
4661 * not use this struct in any new code.
4664 "i", FInt32; (* for historical compatibility *)
4665 "b", FInt32; (* for historical compatibility *)
4668 (* LVM PVs, VGs, LVs. *)
4669 "lvm_pv", lvm_pv_cols;
4670 "lvm_vg", lvm_vg_cols;
4671 "lvm_lv", lvm_lv_cols;
4673 (* Column names and types from stat structures.
4674 * NB. Can't use things like 'st_atime' because glibc header files
4675 * define some of these as macros. Ugh.
4706 (* Column names in dirent structure. *)
4709 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4714 (* Version numbers. *)
4722 (* Extended attribute. *)
4724 "attrname", FString;
4728 (* Inotify events. *)
4732 "in_cookie", FUInt32;
4736 (* Partition table entry. *)
4739 "part_start", FBytes;
4741 "part_size", FBytes;
4743 ] (* end of structs *)
4745 (* Ugh, Java has to be different ..
4746 * These names are also used by the Haskell bindings.
4748 let java_structs = [
4749 "int_bool", "IntBool";
4754 "statvfs", "StatVFS";
4756 "version", "Version";
4758 "inotify_event", "INotifyEvent";
4759 "partition", "Partition";
4762 (* What structs are actually returned. *)
4763 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4765 (* Returns a list of RStruct/RStructList structs that are returned
4766 * by any function. Each element of returned list is a pair:
4768 * (structname, RStructOnly)
4769 * == there exists function which returns RStruct (_, structname)
4770 * (structname, RStructListOnly)
4771 * == there exists function which returns RStructList (_, structname)
4772 * (structname, RStructAndList)
4773 * == there are functions returning both RStruct (_, structname)
4774 * and RStructList (_, structname)
4776 let rstructs_used_by functions =
4777 (* ||| is a "logical OR" for rstructs_used_t *)
4781 | _, RStructAndList -> RStructAndList
4782 | RStructOnly, RStructListOnly
4783 | RStructListOnly, RStructOnly -> RStructAndList
4784 | RStructOnly, RStructOnly -> RStructOnly
4785 | RStructListOnly, RStructListOnly -> RStructListOnly
4788 let h = Hashtbl.create 13 in
4790 (* if elem->oldv exists, update entry using ||| operator,
4791 * else just add elem->newv to the hash
4793 let update elem newv =
4794 try let oldv = Hashtbl.find h elem in
4795 Hashtbl.replace h elem (newv ||| oldv)
4796 with Not_found -> Hashtbl.add h elem newv
4800 fun (_, style, _, _, _, _, _) ->
4801 match fst style with
4802 | RStruct (_, structname) -> update structname RStructOnly
4803 | RStructList (_, structname) -> update structname RStructListOnly
4807 (* return key->values as a list of (key,value) *)
4808 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4810 (* Used for testing language bindings. *)
4812 | CallString of string
4813 | CallOptString of string option
4814 | CallStringList of string list
4816 | CallInt64 of int64
4819 (* Used to memoize the result of pod2text. *)
4820 let pod2text_memo_filename = "src/.pod2text.data"
4821 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4823 let chan = open_in pod2text_memo_filename in
4824 let v = input_value chan in
4828 _ -> Hashtbl.create 13
4829 let pod2text_memo_updated () =
4830 let chan = open_out pod2text_memo_filename in
4831 output_value chan pod2text_memo;
4834 (* Useful functions.
4835 * Note we don't want to use any external OCaml libraries which
4836 * makes this a bit harder than it should be.
4838 module StringMap = Map.Make (String)
4840 let failwithf fs = ksprintf failwith fs
4842 let unique = let i = ref 0 in fun () -> incr i; !i
4844 let replace_char s c1 c2 =
4845 let s2 = String.copy s in
4846 let r = ref false in
4847 for i = 0 to String.length s2 - 1 do
4848 if String.unsafe_get s2 i = c1 then (
4849 String.unsafe_set s2 i c2;
4853 if not !r then s else s2
4857 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4859 let triml ?(test = isspace) str =
4861 let n = ref (String.length str) in
4862 while !n > 0 && test str.[!i]; do
4867 else String.sub str !i !n
4869 let trimr ?(test = isspace) str =
4870 let n = ref (String.length str) in
4871 while !n > 0 && test str.[!n-1]; do
4874 if !n = String.length str then str
4875 else String.sub str 0 !n
4877 let trim ?(test = isspace) str =
4878 trimr ~test (triml ~test str)
4880 let rec find s sub =
4881 let len = String.length s in
4882 let sublen = String.length sub in
4884 if i <= len-sublen then (
4886 if j < sublen then (
4887 if s.[i+j] = sub.[j] then loop2 (j+1)
4893 if r = -1 then loop (i+1) else r
4899 let rec replace_str s s1 s2 =
4900 let len = String.length s in
4901 let sublen = String.length s1 in
4902 let i = find s s1 in
4905 let s' = String.sub s 0 i in
4906 let s'' = String.sub s (i+sublen) (len-i-sublen) in
4907 s' ^ s2 ^ replace_str s'' s1 s2
4910 let rec string_split sep str =
4911 let len = String.length str in
4912 let seplen = String.length sep in
4913 let i = find str sep in
4914 if i = -1 then [str]
4916 let s' = String.sub str 0 i in
4917 let s'' = String.sub str (i+seplen) (len-i-seplen) in
4918 s' :: string_split sep s''
4921 let files_equal n1 n2 =
4922 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4923 match Sys.command cmd with
4926 | i -> failwithf "%s: failed with error code %d" cmd i
4928 let rec filter_map f = function
4932 | Some y -> y :: filter_map f xs
4933 | None -> filter_map f xs
4935 let rec find_map f = function
4936 | [] -> raise Not_found
4940 | None -> find_map f xs
4943 let rec loop i = function
4945 | x :: xs -> f i x; loop (i+1) xs
4950 let rec loop i = function
4952 | x :: xs -> let r = f i x in r :: loop (i+1) xs
4956 let count_chars c str =
4957 let count = ref 0 in
4958 for i = 0 to String.length str - 1 do
4959 if c = String.unsafe_get str i then incr count
4963 let name_of_argt = function
4964 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4965 | StringList n | DeviceList n | Bool n | Int n | Int64 n
4966 | FileIn n | FileOut n -> n
4968 let java_name_of_struct typ =
4969 try List.assoc typ java_structs
4972 "java_name_of_struct: no java_structs entry corresponding to %s" typ
4974 let cols_of_struct typ =
4975 try List.assoc typ structs
4977 failwithf "cols_of_struct: unknown struct %s" typ
4979 let seq_of_test = function
4980 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4981 | TestOutputListOfDevices (s, _)
4982 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4983 | TestOutputTrue s | TestOutputFalse s
4984 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4985 | TestOutputStruct (s, _)
4986 | TestLastFail s -> s
4988 (* Handling for function flags. *)
4989 let protocol_limit_warning =
4990 "Because of the message protocol, there is a transfer limit
4991 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
4993 let danger_will_robinson =
4994 "B<This command is dangerous. Without careful use you
4995 can easily destroy all your data>."
4997 let deprecation_notice flags =
5000 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5002 sprintf "This function is deprecated.
5003 In new code, use the C<%s> call instead.
5005 Deprecated functions will not be removed from the API, but the
5006 fact that they are deprecated indicates that there are problems
5007 with correct use of these functions." alt in
5012 (* Create list of optional groups. *)
5014 let h = Hashtbl.create 13 in
5016 fun (name, _, _, flags, _, _, _) ->
5020 let names = try Hashtbl.find h group with Not_found -> [] in
5021 Hashtbl.replace h group (name :: names)
5025 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5028 fun group -> group, List.sort compare (Hashtbl.find h group)
5030 List.sort (fun x y -> compare (fst x) (fst y)) groups
5032 (* Check function names etc. for consistency. *)
5033 let check_functions () =
5034 let contains_uppercase str =
5035 let len = String.length str in
5037 if i >= len then false
5040 if c >= 'A' && c <= 'Z' then true
5047 (* Check function names. *)
5049 fun (name, _, _, _, _, _, _) ->
5050 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5051 failwithf "function name %s does not need 'guestfs' prefix" name;
5053 failwithf "function name is empty";
5054 if name.[0] < 'a' || name.[0] > 'z' then
5055 failwithf "function name %s must start with lowercase a-z" name;
5056 if String.contains name '-' then
5057 failwithf "function name %s should not contain '-', use '_' instead."
5061 (* Check function parameter/return names. *)
5063 fun (name, style, _, _, _, _, _) ->
5064 let check_arg_ret_name n =
5065 if contains_uppercase n then
5066 failwithf "%s param/ret %s should not contain uppercase chars"
5068 if String.contains n '-' || String.contains n '_' then
5069 failwithf "%s param/ret %s should not contain '-' or '_'"
5072 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;
5073 if n = "int" || n = "char" || n = "short" || n = "long" then
5074 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5075 if n = "i" || n = "n" then
5076 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5077 if n = "argv" || n = "args" then
5078 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5080 (* List Haskell, OCaml and C keywords here.
5081 * http://www.haskell.org/haskellwiki/Keywords
5082 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5083 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5084 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5085 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5086 * Omitting _-containing words, since they're handled above.
5087 * Omitting the OCaml reserved word, "val", is ok,
5088 * and saves us from renaming several parameters.
5091 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5092 "char"; "class"; "const"; "constraint"; "continue"; "data";
5093 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5094 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5095 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5096 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5097 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5099 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5100 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5101 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5102 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5103 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5104 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5105 "volatile"; "when"; "where"; "while";
5107 if List.mem n reserved then
5108 failwithf "%s has param/ret using reserved word %s" name n;
5111 (match fst style with
5113 | RInt n | RInt64 n | RBool n
5114 | RConstString n | RConstOptString n | RString n
5115 | RStringList n | RStruct (n, _) | RStructList (n, _)
5116 | RHashtable n | RBufferOut n ->
5117 check_arg_ret_name n
5119 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5122 (* Check short descriptions. *)
5124 fun (name, _, _, _, _, shortdesc, _) ->
5125 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5126 failwithf "short description of %s should begin with lowercase." name;
5127 let c = shortdesc.[String.length shortdesc-1] in
5128 if c = '\n' || c = '.' then
5129 failwithf "short description of %s should not end with . or \\n." name
5132 (* Check long descriptions. *)
5134 fun (name, _, _, _, _, _, longdesc) ->
5135 if longdesc.[String.length longdesc-1] = '\n' then
5136 failwithf "long description of %s should not end with \\n." name
5139 (* Check proc_nrs. *)
5141 fun (name, _, proc_nr, _, _, _, _) ->
5142 if proc_nr <= 0 then
5143 failwithf "daemon function %s should have proc_nr > 0" name
5147 fun (name, _, proc_nr, _, _, _, _) ->
5148 if proc_nr <> -1 then
5149 failwithf "non-daemon function %s should have proc_nr -1" name
5150 ) non_daemon_functions;
5153 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5156 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5157 let rec loop = function
5160 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5162 | (name1,nr1) :: (name2,nr2) :: _ ->
5163 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5171 (* Ignore functions that have no tests. We generate a
5172 * warning when the user does 'make check' instead.
5174 | name, _, _, _, [], _, _ -> ()
5175 | name, _, _, _, tests, _, _ ->
5179 match seq_of_test test with
5181 failwithf "%s has a test containing an empty sequence" name
5182 | cmds -> List.map List.hd cmds
5184 let funcs = List.flatten funcs in
5186 let tested = List.mem name funcs in
5189 failwithf "function %s has tests but does not test itself" name
5192 (* 'pr' prints to the current output file. *)
5193 let chan = ref Pervasives.stdout
5198 let i = count_chars '\n' str in
5199 lines := !lines + i;
5200 output_string !chan str
5203 let copyright_years =
5204 let this_year = 1900 + (localtime (time ())).tm_year in
5205 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5207 (* Generate a header block in a number of standard styles. *)
5208 type comment_style =
5209 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5210 type license = GPLv2plus | LGPLv2plus
5212 let generate_header ?(extra_inputs = []) comment license =
5213 let inputs = "src/generator.ml" :: extra_inputs in
5214 let c = match comment with
5215 | CStyle -> pr "/* "; " *"
5216 | CPlusPlusStyle -> pr "// "; "//"
5217 | HashStyle -> pr "# "; "#"
5218 | OCamlStyle -> pr "(* "; " *"
5219 | HaskellStyle -> pr "{- "; " " in
5220 pr "libguestfs generated file\n";
5221 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5222 List.iter (pr "%s %s\n" c) inputs;
5223 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5225 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5229 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5230 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5231 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5232 pr "%s (at your option) any later version.\n" c;
5234 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5235 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5236 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5237 pr "%s GNU General Public License for more details.\n" c;
5239 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5240 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5241 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5244 pr "%s This library is free software; you can redistribute it and/or\n" c;
5245 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5246 pr "%s License as published by the Free Software Foundation; either\n" c;
5247 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5249 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5250 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5251 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5252 pr "%s Lesser General Public License for more details.\n" c;
5254 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5255 pr "%s License along with this library; if not, write to the Free Software\n" c;
5256 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5259 | CStyle -> pr " */\n"
5262 | OCamlStyle -> pr " *)\n"
5263 | HaskellStyle -> pr "-}\n"
5267 (* Start of main code generation functions below this line. *)
5269 (* Generate the pod documentation for the C API. *)
5270 let rec generate_actions_pod () =
5272 fun (shortname, style, _, flags, _, _, longdesc) ->
5273 if not (List.mem NotInDocs flags) then (
5274 let name = "guestfs_" ^ shortname in
5275 pr "=head2 %s\n\n" name;
5277 generate_prototype ~extern:false ~handle:"g" name style;
5279 pr "%s\n\n" longdesc;
5280 (match fst style with
5282 pr "This function returns 0 on success or -1 on error.\n\n"
5284 pr "On error this function returns -1.\n\n"
5286 pr "On error this function returns -1.\n\n"
5288 pr "This function returns a C truth value on success or -1 on error.\n\n"
5290 pr "This function returns a string, or NULL on error.
5291 The string is owned by the guest handle and must I<not> be freed.\n\n"
5292 | RConstOptString _ ->
5293 pr "This function returns a string which may be NULL.
5294 There is way to return an error from this function.
5295 The string is owned by the guest handle and must I<not> be freed.\n\n"
5297 pr "This function returns a string, or NULL on error.
5298 I<The caller must free the returned string after use>.\n\n"
5300 pr "This function returns a NULL-terminated array of strings
5301 (like L<environ(3)>), or NULL if there was an error.
5302 I<The caller must free the strings and the array after use>.\n\n"
5303 | RStruct (_, typ) ->
5304 pr "This function returns a C<struct guestfs_%s *>,
5305 or NULL if there was an error.
5306 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5307 | RStructList (_, typ) ->
5308 pr "This function returns a C<struct guestfs_%s_list *>
5309 (see E<lt>guestfs-structs.hE<gt>),
5310 or NULL if there was an error.
5311 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5313 pr "This function returns a NULL-terminated array of
5314 strings, or NULL if there was an error.
5315 The array of strings will always have length C<2n+1>, where
5316 C<n> keys and values alternate, followed by the trailing NULL entry.
5317 I<The caller must free the strings and the array after use>.\n\n"
5319 pr "This function returns a buffer, or NULL on error.
5320 The size of the returned buffer is written to C<*size_r>.
5321 I<The caller must free the returned buffer after use>.\n\n"
5323 if List.mem ProtocolLimitWarning flags then
5324 pr "%s\n\n" protocol_limit_warning;
5325 if List.mem DangerWillRobinson flags then
5326 pr "%s\n\n" danger_will_robinson;
5327 match deprecation_notice flags with
5329 | Some txt -> pr "%s\n\n" txt
5331 ) all_functions_sorted
5333 and generate_structs_pod () =
5334 (* Structs documentation. *)
5337 pr "=head2 guestfs_%s\n" typ;
5339 pr " struct guestfs_%s {\n" typ;
5342 | name, FChar -> pr " char %s;\n" name
5343 | name, FUInt32 -> pr " uint32_t %s;\n" name
5344 | name, FInt32 -> pr " int32_t %s;\n" name
5345 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5346 | name, FInt64 -> pr " int64_t %s;\n" name
5347 | name, FString -> pr " char *%s;\n" name
5349 pr " /* The next two fields describe a byte array. */\n";
5350 pr " uint32_t %s_len;\n" name;
5351 pr " char *%s;\n" name
5353 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5354 pr " char %s[32];\n" name
5355 | name, FOptPercent ->
5356 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5357 pr " float %s;\n" name
5361 pr " struct guestfs_%s_list {\n" typ;
5362 pr " uint32_t len; /* Number of elements in list. */\n";
5363 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5366 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5367 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5372 and generate_availability_pod () =
5373 (* Availability documentation. *)
5377 fun (group, functions) ->
5378 pr "=item B<%s>\n" group;
5380 pr "The following functions:\n";
5381 List.iter (pr "L</guestfs_%s>\n") functions;
5387 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5388 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5390 * We have to use an underscore instead of a dash because otherwise
5391 * rpcgen generates incorrect code.
5393 * This header is NOT exported to clients, but see also generate_structs_h.
5395 and generate_xdr () =
5396 generate_header CStyle LGPLv2plus;
5398 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5399 pr "typedef string str<>;\n";
5402 (* Internal structures. *)
5406 pr "struct guestfs_int_%s {\n" typ;
5408 | name, FChar -> pr " char %s;\n" name
5409 | name, FString -> pr " string %s<>;\n" name
5410 | name, FBuffer -> pr " opaque %s<>;\n" name
5411 | name, FUUID -> pr " opaque %s[32];\n" name
5412 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5413 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5414 | name, FOptPercent -> pr " float %s;\n" name
5418 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5423 fun (shortname, style, _, _, _, _, _) ->
5424 let name = "guestfs_" ^ shortname in
5426 (match snd style with
5429 pr "struct %s_args {\n" name;
5432 | Pathname n | Device n | Dev_or_Path n | String n ->
5433 pr " string %s<>;\n" n
5434 | OptString n -> pr " str *%s;\n" n
5435 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5436 | Bool n -> pr " bool %s;\n" n
5437 | Int n -> pr " int %s;\n" n
5438 | Int64 n -> pr " hyper %s;\n" n
5439 | FileIn _ | FileOut _ -> ()
5443 (match fst style with
5446 pr "struct %s_ret {\n" name;
5450 pr "struct %s_ret {\n" name;
5451 pr " hyper %s;\n" n;
5454 pr "struct %s_ret {\n" name;
5457 | RConstString _ | RConstOptString _ ->
5458 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5460 pr "struct %s_ret {\n" name;
5461 pr " string %s<>;\n" n;
5464 pr "struct %s_ret {\n" name;
5465 pr " str %s<>;\n" n;
5467 | RStruct (n, typ) ->
5468 pr "struct %s_ret {\n" name;
5469 pr " guestfs_int_%s %s;\n" typ n;
5471 | RStructList (n, typ) ->
5472 pr "struct %s_ret {\n" name;
5473 pr " guestfs_int_%s_list %s;\n" typ n;
5476 pr "struct %s_ret {\n" name;
5477 pr " str %s<>;\n" n;
5480 pr "struct %s_ret {\n" name;
5481 pr " opaque %s<>;\n" n;
5486 (* Table of procedure numbers. *)
5487 pr "enum guestfs_procedure {\n";
5489 fun (shortname, _, proc_nr, _, _, _, _) ->
5490 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5492 pr " GUESTFS_PROC_NR_PROCS\n";
5496 (* Having to choose a maximum message size is annoying for several
5497 * reasons (it limits what we can do in the API), but it (a) makes
5498 * the protocol a lot simpler, and (b) provides a bound on the size
5499 * of the daemon which operates in limited memory space.
5501 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5504 (* Message header, etc. *)
5506 /* The communication protocol is now documented in the guestfs(3)
5510 const GUESTFS_PROGRAM = 0x2000F5F5;
5511 const GUESTFS_PROTOCOL_VERSION = 1;
5513 /* These constants must be larger than any possible message length. */
5514 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5515 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5517 enum guestfs_message_direction {
5518 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5519 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5522 enum guestfs_message_status {
5523 GUESTFS_STATUS_OK = 0,
5524 GUESTFS_STATUS_ERROR = 1
5527 const GUESTFS_ERROR_LEN = 256;
5529 struct guestfs_message_error {
5530 string error_message<GUESTFS_ERROR_LEN>;
5533 struct guestfs_message_header {
5534 unsigned prog; /* GUESTFS_PROGRAM */
5535 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5536 guestfs_procedure proc; /* GUESTFS_PROC_x */
5537 guestfs_message_direction direction;
5538 unsigned serial; /* message serial number */
5539 guestfs_message_status status;
5542 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5544 struct guestfs_chunk {
5545 int cancel; /* if non-zero, transfer is cancelled */
5546 /* data size is 0 bytes if the transfer has finished successfully */
5547 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5551 (* Generate the guestfs-structs.h file. *)
5552 and generate_structs_h () =
5553 generate_header CStyle LGPLv2plus;
5555 (* This is a public exported header file containing various
5556 * structures. The structures are carefully written to have
5557 * exactly the same in-memory format as the XDR structures that
5558 * we use on the wire to the daemon. The reason for creating
5559 * copies of these structures here is just so we don't have to
5560 * export the whole of guestfs_protocol.h (which includes much
5561 * unrelated and XDR-dependent stuff that we don't want to be
5562 * public, or required by clients).
5564 * To reiterate, we will pass these structures to and from the
5565 * client with a simple assignment or memcpy, so the format
5566 * must be identical to what rpcgen / the RFC defines.
5569 (* Public structures. *)
5572 pr "struct guestfs_%s {\n" typ;
5575 | name, FChar -> pr " char %s;\n" name
5576 | name, FString -> pr " char *%s;\n" name
5578 pr " uint32_t %s_len;\n" name;
5579 pr " char *%s;\n" name
5580 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5581 | name, FUInt32 -> pr " uint32_t %s;\n" name
5582 | name, FInt32 -> pr " int32_t %s;\n" name
5583 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5584 | name, FInt64 -> pr " int64_t %s;\n" name
5585 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5589 pr "struct guestfs_%s_list {\n" typ;
5590 pr " uint32_t len;\n";
5591 pr " struct guestfs_%s *val;\n" typ;
5594 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5595 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5599 (* Generate the guestfs-actions.h file. *)
5600 and generate_actions_h () =
5601 generate_header CStyle LGPLv2plus;
5603 fun (shortname, style, _, _, _, _, _) ->
5604 let name = "guestfs_" ^ shortname in
5605 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5609 (* Generate the guestfs-internal-actions.h file. *)
5610 and generate_internal_actions_h () =
5611 generate_header CStyle LGPLv2plus;
5613 fun (shortname, style, _, _, _, _, _) ->
5614 let name = "guestfs__" ^ shortname in
5615 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5617 ) non_daemon_functions
5619 (* Generate the client-side dispatch stubs. *)
5620 and generate_client_actions () =
5621 generate_header CStyle LGPLv2plus;
5628 #include <inttypes.h>
5630 #include \"guestfs.h\"
5631 #include \"guestfs-internal.h\"
5632 #include \"guestfs-internal-actions.h\"
5633 #include \"guestfs_protocol.h\"
5635 #define error guestfs_error
5636 //#define perrorf guestfs_perrorf
5637 #define safe_malloc guestfs_safe_malloc
5638 #define safe_realloc guestfs_safe_realloc
5639 //#define safe_strdup guestfs_safe_strdup
5640 #define safe_memdup guestfs_safe_memdup
5642 /* Check the return message from a call for validity. */
5644 check_reply_header (guestfs_h *g,
5645 const struct guestfs_message_header *hdr,
5646 unsigned int proc_nr, unsigned int serial)
5648 if (hdr->prog != GUESTFS_PROGRAM) {
5649 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5652 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5653 error (g, \"wrong protocol version (%%d/%%d)\",
5654 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5657 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5658 error (g, \"unexpected message direction (%%d/%%d)\",
5659 hdr->direction, GUESTFS_DIRECTION_REPLY);
5662 if (hdr->proc != proc_nr) {
5663 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5666 if (hdr->serial != serial) {
5667 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5674 /* Check we are in the right state to run a high-level action. */
5676 check_state (guestfs_h *g, const char *caller)
5678 if (!guestfs__is_ready (g)) {
5679 if (guestfs__is_config (g) || guestfs__is_launching (g))
5680 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5683 error (g, \"%%s called from the wrong state, %%d != READY\",
5684 caller, guestfs__get_state (g));
5692 (* Generate code to generate guestfish call traces. *)
5693 let trace_call shortname style =
5694 pr " if (guestfs__get_trace (g)) {\n";
5697 List.exists (function
5698 | StringList _ | DeviceList _ -> true
5699 | _ -> false) (snd style) in
5705 pr " printf (\"%s\");\n" shortname;
5708 | String n (* strings *)
5714 (* guestfish doesn't support string escaping, so neither do we *)
5715 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
5716 | OptString n -> (* string option *)
5717 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5718 pr " else printf (\" null\");\n"
5720 | DeviceList n -> (* string list *)
5721 pr " putchar (' ');\n";
5722 pr " putchar ('\"');\n";
5723 pr " for (i = 0; %s[i]; ++i) {\n" n;
5724 pr " if (i > 0) putchar (' ');\n";
5725 pr " fputs (%s[i], stdout);\n" n;
5727 pr " putchar ('\"');\n";
5728 | Bool n -> (* boolean *)
5729 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
5730 | Int n -> (* int *)
5731 pr " printf (\" %%d\", %s);\n" n
5733 pr " printf (\" %%\" PRIi64, %s);\n" n
5735 pr " putchar ('\\n');\n";
5740 (* For non-daemon functions, generate a wrapper around each function. *)
5742 fun (shortname, style, _, _, _, _, _) ->
5743 let name = "guestfs_" ^ shortname in
5745 generate_prototype ~extern:false ~semicolon:false ~newline:true
5746 ~handle:"g" name style;
5748 trace_call shortname style;
5749 pr " return guestfs__%s " shortname;
5750 generate_c_call_args ~handle:"g" style;
5754 ) non_daemon_functions;
5756 (* Client-side stubs for each function. *)
5758 fun (shortname, style, _, _, _, _, _) ->
5759 let name = "guestfs_" ^ shortname in
5761 (* Generate the action stub. *)
5762 generate_prototype ~extern:false ~semicolon:false ~newline:true
5763 ~handle:"g" name style;
5766 match fst style with
5767 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5768 | RConstString _ | RConstOptString _ ->
5769 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5770 | RString _ | RStringList _
5771 | RStruct _ | RStructList _
5772 | RHashtable _ | RBufferOut _ ->
5777 (match snd style with
5779 | _ -> pr " struct %s_args args;\n" name
5782 pr " guestfs_message_header hdr;\n";
5783 pr " guestfs_message_error err;\n";
5785 match fst style with
5787 | RConstString _ | RConstOptString _ ->
5788 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5790 | RBool _ | RString _ | RStringList _
5791 | RStruct _ | RStructList _
5792 | RHashtable _ | RBufferOut _ ->
5793 pr " struct %s_ret ret;\n" name;
5796 pr " int serial;\n";
5799 trace_call shortname style;
5800 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
5801 shortname error_code;
5802 pr " guestfs___set_busy (g);\n";
5805 (* Send the main header and arguments. *)
5806 (match snd style with
5808 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5809 (String.uppercase shortname)
5813 | Pathname n | Device n | Dev_or_Path n | String n ->
5814 pr " args.%s = (char *) %s;\n" n n
5816 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
5817 | StringList n | DeviceList n ->
5818 pr " args.%s.%s_val = (char **) %s;\n" n n n;
5819 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5821 pr " args.%s = %s;\n" n n
5823 pr " args.%s = %s;\n" n n
5825 pr " args.%s = %s;\n" n n
5826 | FileIn _ | FileOut _ -> ()
5828 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5829 (String.uppercase shortname);
5830 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5833 pr " if (serial == -1) {\n";
5834 pr " guestfs___end_busy (g);\n";
5835 pr " return %s;\n" error_code;
5839 (* Send any additional files (FileIn) requested. *)
5840 let need_read_reply_label = ref false in
5844 pr " r = guestfs___send_file (g, %s);\n" n;
5845 pr " if (r == -1) {\n";
5846 pr " guestfs___end_busy (g);\n";
5847 pr " return %s;\n" error_code;
5849 pr " if (r == -2) /* daemon cancelled */\n";
5850 pr " goto read_reply;\n";
5851 need_read_reply_label := true;
5856 (* Wait for the reply from the remote end. *)
5857 if !need_read_reply_label then pr " read_reply:\n";
5858 pr " memset (&hdr, 0, sizeof hdr);\n";
5859 pr " memset (&err, 0, sizeof err);\n";
5860 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
5862 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
5866 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5869 pr " if (r == -1) {\n";
5870 pr " guestfs___end_busy (g);\n";
5871 pr " return %s;\n" error_code;
5875 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5876 (String.uppercase shortname);
5877 pr " guestfs___end_busy (g);\n";
5878 pr " return %s;\n" error_code;
5882 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5883 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5884 pr " free (err.error_message);\n";
5885 pr " guestfs___end_busy (g);\n";
5886 pr " return %s;\n" error_code;
5890 (* Expecting to receive further files (FileOut)? *)
5894 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
5895 pr " guestfs___end_busy (g);\n";
5896 pr " return %s;\n" error_code;
5902 pr " guestfs___end_busy (g);\n";
5904 (match fst style with
5905 | RErr -> pr " return 0;\n"
5906 | RInt n | RInt64 n | RBool n ->
5907 pr " return ret.%s;\n" n
5908 | RConstString _ | RConstOptString _ ->
5909 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5911 pr " return ret.%s; /* caller will free */\n" n
5912 | RStringList n | RHashtable n ->
5913 pr " /* caller will free this, but we need to add a NULL entry */\n";
5914 pr " ret.%s.%s_val =\n" n n;
5915 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
5916 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
5918 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5919 pr " return ret.%s.%s_val;\n" n n
5921 pr " /* caller will free this */\n";
5922 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5923 | RStructList (n, _) ->
5924 pr " /* caller will free this */\n";
5925 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5927 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5928 pr " * _val might be NULL here. To make the API saner for\n";
5929 pr " * callers, we turn this case into a unique pointer (using\n";
5930 pr " * malloc(1)).\n";
5932 pr " if (ret.%s.%s_len > 0) {\n" n n;
5933 pr " *size_r = ret.%s.%s_len;\n" n n;
5934 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
5936 pr " free (ret.%s.%s_val);\n" n n;
5937 pr " char *p = safe_malloc (g, 1);\n";
5938 pr " *size_r = ret.%s.%s_len;\n" n n;
5946 (* Functions to free structures. *)
5947 pr "/* Structure-freeing functions. These rely on the fact that the\n";
5948 pr " * structure format is identical to the XDR format. See note in\n";
5949 pr " * generator.ml.\n";
5956 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5958 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5964 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5966 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5973 (* Generate daemon/actions.h. *)
5974 and generate_daemon_actions_h () =
5975 generate_header CStyle GPLv2plus;
5977 pr "#include \"../src/guestfs_protocol.h\"\n";
5981 fun (name, style, _, _, _, _, _) ->
5983 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5987 (* Generate the linker script which controls the visibility of
5988 * symbols in the public ABI and ensures no other symbols get
5989 * exported accidentally.
5991 and generate_linker_script () =
5992 generate_header HashStyle GPLv2plus;
5997 "guestfs_get_error_handler";
5998 "guestfs_get_out_of_memory_handler";
5999 "guestfs_last_error";
6000 "guestfs_set_error_handler";
6001 "guestfs_set_launch_done_callback";
6002 "guestfs_set_log_message_callback";
6003 "guestfs_set_out_of_memory_handler";
6004 "guestfs_set_subprocess_quit_callback";
6006 (* Unofficial parts of the API: the bindings code use these
6007 * functions, so it is useful to export them.
6009 "guestfs_safe_calloc";
6010 "guestfs_safe_malloc";
6013 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6017 List.map (fun (typ, _) ->
6018 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6021 let globals = List.sort compare (globals @ functions @ structs) in
6025 List.iter (pr " %s;\n") globals;
6032 (* Generate the server-side stubs. *)
6033 and generate_daemon_actions () =
6034 generate_header CStyle GPLv2plus;
6036 pr "#include <config.h>\n";
6038 pr "#include <stdio.h>\n";
6039 pr "#include <stdlib.h>\n";
6040 pr "#include <string.h>\n";
6041 pr "#include <inttypes.h>\n";
6042 pr "#include <rpc/types.h>\n";
6043 pr "#include <rpc/xdr.h>\n";
6045 pr "#include \"daemon.h\"\n";
6046 pr "#include \"c-ctype.h\"\n";
6047 pr "#include \"../src/guestfs_protocol.h\"\n";
6048 pr "#include \"actions.h\"\n";
6052 fun (name, style, _, _, _, _, _) ->
6053 (* Generate server-side stubs. *)
6054 pr "static void %s_stub (XDR *xdr_in)\n" name;
6057 match fst style with
6058 | RErr | RInt _ -> pr " int r;\n"; "-1"
6059 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6060 | RBool _ -> pr " int r;\n"; "-1"
6061 | RConstString _ | RConstOptString _ ->
6062 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6063 | RString _ -> pr " char *r;\n"; "NULL"
6064 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6065 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6066 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6068 pr " size_t size = 1;\n";
6072 (match snd style with
6075 pr " struct guestfs_%s_args args;\n" name;
6078 | Device n | Dev_or_Path n
6081 | OptString n -> pr " char *%s;\n" n
6082 | StringList n | DeviceList n -> pr " char **%s;\n" n
6083 | Bool n -> pr " int %s;\n" n
6084 | Int n -> pr " int %s;\n" n
6085 | Int64 n -> pr " int64_t %s;\n" n
6086 | FileIn _ | FileOut _ -> ()
6092 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6094 (match snd style with
6097 pr " memset (&args, 0, sizeof args);\n";
6099 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6101 pr " cancel_receive ();\n";
6102 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6106 pr " char *%s = args.%s;\n" n n
6108 let pr_list_handling_code n =
6109 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6110 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6111 pr " if (%s == NULL) {\n" n;
6113 pr " cancel_receive ();\n";
6114 pr " reply_with_perror (\"realloc\");\n";
6117 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6118 pr " args.%s.%s_val = %s;\n" n n n;
6124 pr " ABS_PATH (%s, %s, goto done);\n"
6125 n (if is_filein then "cancel_receive ()" else "");
6128 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6129 n (if is_filein then "cancel_receive ()" else "");
6132 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6133 n (if is_filein then "cancel_receive ()" else "");
6134 | String n -> pr_args n
6135 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6137 pr_list_handling_code n;
6139 pr_list_handling_code n;
6140 pr " /* Ensure that each is a device,\n";
6141 pr " * and perform device name translation. */\n";
6142 pr " { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6143 pr " RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6144 (if is_filein then "cancel_receive ()" else "");
6146 | Bool n -> pr " %s = args.%s;\n" n n
6147 | Int n -> pr " %s = args.%s;\n" n n
6148 | Int64 n -> pr " %s = args.%s;\n" n n
6149 | FileIn _ | FileOut _ -> ()
6155 (* this is used at least for do_equal *)
6156 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6157 (* Emit NEED_ROOT just once, even when there are two or
6158 more Pathname args *)
6159 pr " NEED_ROOT (%s, goto done);\n"
6160 (if is_filein then "cancel_receive ()" else "");
6163 (* Don't want to call the impl with any FileIn or FileOut
6164 * parameters, since these go "outside" the RPC protocol.
6167 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6169 pr " r = do_%s " name;
6170 generate_c_call_args (fst style, args');
6173 (match fst style with
6174 | RErr | RInt _ | RInt64 _ | RBool _
6175 | RConstString _ | RConstOptString _
6176 | RString _ | RStringList _ | RHashtable _
6177 | RStruct (_, _) | RStructList (_, _) ->
6178 pr " if (r == %s)\n" error_code;
6179 pr " /* do_%s has already called reply_with_error */\n" name;
6183 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6184 pr " * an ordinary zero-length buffer), so be careful ...\n";
6186 pr " if (size == 1 && r == %s)\n" error_code;
6187 pr " /* do_%s has already called reply_with_error */\n" name;
6192 (* If there are any FileOut parameters, then the impl must
6193 * send its own reply.
6196 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6198 pr " /* do_%s has already sent a reply */\n" name
6200 match fst style with
6201 | RErr -> pr " reply (NULL, NULL);\n"
6202 | RInt n | RInt64 n | RBool n ->
6203 pr " struct guestfs_%s_ret ret;\n" name;
6204 pr " ret.%s = r;\n" n;
6205 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6207 | RConstString _ | RConstOptString _ ->
6208 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6210 pr " struct guestfs_%s_ret ret;\n" name;
6211 pr " ret.%s = r;\n" n;
6212 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6215 | RStringList n | RHashtable n ->
6216 pr " struct guestfs_%s_ret ret;\n" name;
6217 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6218 pr " ret.%s.%s_val = r;\n" n n;
6219 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6221 pr " free_strings (r);\n"
6223 pr " struct guestfs_%s_ret ret;\n" name;
6224 pr " ret.%s = *r;\n" n;
6225 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6227 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6229 | RStructList (n, _) ->
6230 pr " struct guestfs_%s_ret ret;\n" name;
6231 pr " ret.%s = *r;\n" n;
6232 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6234 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6237 pr " struct guestfs_%s_ret ret;\n" name;
6238 pr " ret.%s.%s_val = r;\n" n n;
6239 pr " ret.%s.%s_len = size;\n" n n;
6240 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6245 (* Free the args. *)
6247 (match snd style with
6250 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6257 (* Dispatch function. *)
6258 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6260 pr " switch (proc_nr) {\n";
6263 fun (name, style, _, _, _, _, _) ->
6264 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6265 pr " %s_stub (xdr_in);\n" name;
6270 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";
6275 (* LVM columns and tokenization functions. *)
6276 (* XXX This generates crap code. We should rethink how we
6282 pr "static const char *lvm_%s_cols = \"%s\";\n"
6283 typ (String.concat "," (List.map fst cols));
6286 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6288 pr " char *tok, *p, *next;\n";
6292 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6295 pr " if (!str) {\n";
6296 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6299 pr " if (!*str || c_isspace (*str)) {\n";
6300 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6305 fun (name, coltype) ->
6306 pr " if (!tok) {\n";
6307 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6310 pr " p = strchrnul (tok, ',');\n";
6311 pr " if (*p) next = p+1; else next = NULL;\n";
6312 pr " *p = '\\0';\n";
6315 pr " r->%s = strdup (tok);\n" name;
6316 pr " if (r->%s == NULL) {\n" name;
6317 pr " perror (\"strdup\");\n";
6321 pr " for (i = j = 0; i < 32; ++j) {\n";
6322 pr " if (tok[j] == '\\0') {\n";
6323 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6325 pr " } else if (tok[j] != '-')\n";
6326 pr " r->%s[i++] = tok[j];\n" name;
6329 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6330 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6334 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6335 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6339 pr " if (tok[0] == '\\0')\n";
6340 pr " r->%s = -1;\n" name;
6341 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6342 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6345 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6346 assert false (* can never be an LVM column *)
6348 pr " tok = next;\n";
6351 pr " if (tok != NULL) {\n";
6352 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6359 pr "guestfs_int_lvm_%s_list *\n" typ;
6360 pr "parse_command_line_%ss (void)\n" typ;
6362 pr " char *out, *err;\n";
6363 pr " char *p, *pend;\n";
6365 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6366 pr " void *newp;\n";
6368 pr " ret = malloc (sizeof *ret);\n";
6369 pr " if (!ret) {\n";
6370 pr " reply_with_perror (\"malloc\");\n";
6371 pr " return NULL;\n";
6374 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6375 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6377 pr " r = command (&out, &err,\n";
6378 pr " \"lvm\", \"%ss\",\n" typ;
6379 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6380 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6381 pr " if (r == -1) {\n";
6382 pr " reply_with_error (\"%%s\", err);\n";
6383 pr " free (out);\n";
6384 pr " free (err);\n";
6385 pr " free (ret);\n";
6386 pr " return NULL;\n";
6389 pr " free (err);\n";
6391 pr " /* Tokenize each line of the output. */\n";
6394 pr " while (p) {\n";
6395 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6396 pr " if (pend) {\n";
6397 pr " *pend = '\\0';\n";
6401 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6404 pr " if (!*p) { /* Empty line? Skip it. */\n";
6409 pr " /* Allocate some space to store this next entry. */\n";
6410 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6411 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6412 pr " if (newp == NULL) {\n";
6413 pr " reply_with_perror (\"realloc\");\n";
6414 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6415 pr " free (ret);\n";
6416 pr " free (out);\n";
6417 pr " return NULL;\n";
6419 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6421 pr " /* Tokenize the next entry. */\n";
6422 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6423 pr " if (r == -1) {\n";
6424 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6425 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6426 pr " free (ret);\n";
6427 pr " free (out);\n";
6428 pr " return NULL;\n";
6435 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6437 pr " free (out);\n";
6438 pr " return ret;\n";
6441 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6443 (* Generate a list of function names, for debugging in the daemon.. *)
6444 and generate_daemon_names () =
6445 generate_header CStyle GPLv2plus;
6447 pr "#include <config.h>\n";
6449 pr "#include \"daemon.h\"\n";
6452 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6453 pr "const char *function_names[] = {\n";
6455 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6459 (* Generate the optional groups for the daemon to implement
6460 * guestfs_available.
6462 and generate_daemon_optgroups_c () =
6463 generate_header CStyle GPLv2plus;
6465 pr "#include <config.h>\n";
6467 pr "#include \"daemon.h\"\n";
6468 pr "#include \"optgroups.h\"\n";
6471 pr "struct optgroup optgroups[] = {\n";
6474 pr " { \"%s\", optgroup_%s_available },\n" group group
6476 pr " { NULL, NULL }\n";
6479 and generate_daemon_optgroups_h () =
6480 generate_header CStyle GPLv2plus;
6484 pr "extern int optgroup_%s_available (void);\n" group
6487 (* Generate the tests. *)
6488 and generate_tests () =
6489 generate_header CStyle GPLv2plus;
6496 #include <sys/types.h>
6499 #include \"guestfs.h\"
6500 #include \"guestfs-internal.h\"
6502 static guestfs_h *g;
6503 static int suppress_error = 0;
6505 static void print_error (guestfs_h *g, void *data, const char *msg)
6507 if (!suppress_error)
6508 fprintf (stderr, \"%%s\\n\", msg);
6511 /* FIXME: nearly identical code appears in fish.c */
6512 static void print_strings (char *const *argv)
6516 for (argc = 0; argv[argc] != NULL; ++argc)
6517 printf (\"\\t%%s\\n\", argv[argc]);
6521 static void print_table (char const *const *argv)
6525 for (i = 0; argv[i] != NULL; i += 2)
6526 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6532 (* Generate a list of commands which are not tested anywhere. *)
6533 pr "static void no_test_warnings (void)\n";
6536 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6538 fun (_, _, _, _, tests, _, _) ->
6539 let tests = filter_map (
6541 | (_, (Always|If _|Unless _), test) -> Some test
6542 | (_, Disabled, _) -> None
6544 let seq = List.concat (List.map seq_of_test tests) in
6545 let cmds_tested = List.map List.hd seq in
6546 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6550 fun (name, _, _, _, _, _, _) ->
6551 if not (Hashtbl.mem hash name) then
6552 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6558 (* Generate the actual tests. Note that we generate the tests
6559 * in reverse order, deliberately, so that (in general) the
6560 * newest tests run first. This makes it quicker and easier to
6565 fun (name, _, _, flags, tests, _, _) ->
6566 mapi (generate_one_test name flags) tests
6567 ) (List.rev all_functions) in
6568 let test_names = List.concat test_names in
6569 let nr_tests = List.length test_names in
6572 int main (int argc, char *argv[])
6575 unsigned long int n_failed = 0;
6576 const char *filename;
6578 int nr_tests, test_num = 0;
6580 setbuf (stdout, NULL);
6582 no_test_warnings ();
6584 g = guestfs_create ();
6586 printf (\"guestfs_create FAILED\\n\");
6587 exit (EXIT_FAILURE);
6590 guestfs_set_error_handler (g, print_error, NULL);
6592 guestfs_set_path (g, \"../appliance\");
6594 filename = \"test1.img\";
6595 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6598 exit (EXIT_FAILURE);
6600 if (lseek (fd, %d, SEEK_SET) == -1) {
6604 exit (EXIT_FAILURE);
6606 if (write (fd, &c, 1) == -1) {
6610 exit (EXIT_FAILURE);
6612 if (close (fd) == -1) {
6615 exit (EXIT_FAILURE);
6617 if (guestfs_add_drive (g, filename) == -1) {
6618 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6619 exit (EXIT_FAILURE);
6622 filename = \"test2.img\";
6623 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6626 exit (EXIT_FAILURE);
6628 if (lseek (fd, %d, SEEK_SET) == -1) {
6632 exit (EXIT_FAILURE);
6634 if (write (fd, &c, 1) == -1) {
6638 exit (EXIT_FAILURE);
6640 if (close (fd) == -1) {
6643 exit (EXIT_FAILURE);
6645 if (guestfs_add_drive (g, filename) == -1) {
6646 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6647 exit (EXIT_FAILURE);
6650 filename = \"test3.img\";
6651 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6654 exit (EXIT_FAILURE);
6656 if (lseek (fd, %d, SEEK_SET) == -1) {
6660 exit (EXIT_FAILURE);
6662 if (write (fd, &c, 1) == -1) {
6666 exit (EXIT_FAILURE);
6668 if (close (fd) == -1) {
6671 exit (EXIT_FAILURE);
6673 if (guestfs_add_drive (g, filename) == -1) {
6674 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6675 exit (EXIT_FAILURE);
6678 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6679 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6680 exit (EXIT_FAILURE);
6683 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6686 if (guestfs_launch (g) == -1) {
6687 printf (\"guestfs_launch FAILED\\n\");
6688 exit (EXIT_FAILURE);
6691 /* Cancel previous alarm. */
6696 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6700 pr " test_num++;\n";
6701 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6702 pr " if (%s () == -1) {\n" test_name;
6703 pr " printf (\"%s FAILED\\n\");\n" test_name;
6704 pr " n_failed++;\n";
6709 pr " guestfs_close (g);\n";
6710 pr " unlink (\"test1.img\");\n";
6711 pr " unlink (\"test2.img\");\n";
6712 pr " unlink (\"test3.img\");\n";
6715 pr " if (n_failed > 0) {\n";
6716 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6717 pr " exit (EXIT_FAILURE);\n";
6721 pr " exit (EXIT_SUCCESS);\n";
6724 and generate_one_test name flags i (init, prereq, test) =
6725 let test_name = sprintf "test_%s_%d" name i in
6728 static int %s_skip (void)
6732 str = getenv (\"TEST_ONLY\");
6734 return strstr (str, \"%s\") == NULL;
6735 str = getenv (\"SKIP_%s\");
6736 if (str && STREQ (str, \"1\")) return 1;
6737 str = getenv (\"SKIP_TEST_%s\");
6738 if (str && STREQ (str, \"1\")) return 1;
6742 " test_name name (String.uppercase test_name) (String.uppercase name);
6745 | Disabled | Always -> ()
6746 | If code | Unless code ->
6747 pr "static int %s_prereq (void)\n" test_name;
6755 static int %s (void)
6758 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
6762 " test_name test_name test_name;
6764 (* Optional functions should only be tested if the relevant
6765 * support is available in the daemon.
6771 pr " const char *groups[] = { \"%s\", NULL };\n" group;
6773 pr " suppress_error = 1;\n";
6774 pr " r = guestfs_available (g, (char **) groups);\n";
6775 pr " suppress_error = 0;\n";
6776 pr " if (r == -1) {\n";
6777 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6786 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6788 pr " if (! %s_prereq ()) {\n" test_name;
6789 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6793 generate_one_test_body name i test_name init test;
6795 pr " if (%s_prereq ()) {\n" test_name;
6796 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6800 generate_one_test_body name i test_name init test;
6802 generate_one_test_body name i test_name init test
6810 and generate_one_test_body name i test_name init test =
6812 | InitNone (* XXX at some point, InitNone and InitEmpty became
6813 * folded together as the same thing. Really we should
6814 * make InitNone do nothing at all, but the tests may
6815 * need to be checked to make sure this is OK.
6818 pr " /* InitNone|InitEmpty for %s */\n" test_name;
6819 List.iter (generate_test_command_call test_name)
6820 [["blockdev_setrw"; "/dev/sda"];
6824 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6825 List.iter (generate_test_command_call test_name)
6826 [["blockdev_setrw"; "/dev/sda"];
6829 ["part_disk"; "/dev/sda"; "mbr"]]
6831 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6832 List.iter (generate_test_command_call test_name)
6833 [["blockdev_setrw"; "/dev/sda"];
6836 ["part_disk"; "/dev/sda"; "mbr"];
6837 ["mkfs"; "ext2"; "/dev/sda1"];
6838 ["mount_options"; ""; "/dev/sda1"; "/"]]
6839 | InitBasicFSonLVM ->
6840 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6842 List.iter (generate_test_command_call test_name)
6843 [["blockdev_setrw"; "/dev/sda"];
6846 ["part_disk"; "/dev/sda"; "mbr"];
6847 ["pvcreate"; "/dev/sda1"];
6848 ["vgcreate"; "VG"; "/dev/sda1"];
6849 ["lvcreate"; "LV"; "VG"; "8"];
6850 ["mkfs"; "ext2"; "/dev/VG/LV"];
6851 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6853 pr " /* InitISOFS for %s */\n" test_name;
6854 List.iter (generate_test_command_call test_name)
6855 [["blockdev_setrw"; "/dev/sda"];
6858 ["mount_ro"; "/dev/sdd"; "/"]]
6861 let get_seq_last = function
6863 failwithf "%s: you cannot use [] (empty list) when expecting a command"
6866 let seq = List.rev seq in
6867 List.rev (List.tl seq), List.hd seq
6872 pr " /* TestRun for %s (%d) */\n" name i;
6873 List.iter (generate_test_command_call test_name) seq
6874 | TestOutput (seq, expected) ->
6875 pr " /* TestOutput for %s (%d) */\n" name i;
6876 pr " const char *expected = \"%s\";\n" (c_quote expected);
6877 let seq, last = get_seq_last seq in
6879 pr " if (STRNEQ (r, expected)) {\n";
6880 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6884 List.iter (generate_test_command_call test_name) seq;
6885 generate_test_command_call ~test test_name last
6886 | TestOutputList (seq, expected) ->
6887 pr " /* TestOutputList for %s (%d) */\n" name i;
6888 let seq, last = get_seq_last seq in
6892 pr " if (!r[%d]) {\n" i;
6893 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6894 pr " print_strings (r);\n";
6898 pr " const char *expected = \"%s\";\n" (c_quote str);
6899 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6900 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6905 pr " if (r[%d] != NULL) {\n" (List.length expected);
6906 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6908 pr " print_strings (r);\n";
6912 List.iter (generate_test_command_call test_name) seq;
6913 generate_test_command_call ~test test_name last
6914 | TestOutputListOfDevices (seq, expected) ->
6915 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
6916 let seq, last = get_seq_last seq in
6920 pr " if (!r[%d]) {\n" i;
6921 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6922 pr " print_strings (r);\n";
6926 pr " const char *expected = \"%s\";\n" (c_quote str);
6927 pr " r[%d][5] = 's';\n" i;
6928 pr " if (STRNEQ (r[%d], expected)) {\n" i;
6929 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6934 pr " if (r[%d] != NULL) {\n" (List.length expected);
6935 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6937 pr " print_strings (r);\n";
6941 List.iter (generate_test_command_call test_name) seq;
6942 generate_test_command_call ~test test_name last
6943 | TestOutputInt (seq, expected) ->
6944 pr " /* TestOutputInt for %s (%d) */\n" name i;
6945 let seq, last = get_seq_last seq in
6947 pr " if (r != %d) {\n" expected;
6948 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6954 List.iter (generate_test_command_call test_name) seq;
6955 generate_test_command_call ~test test_name last
6956 | TestOutputIntOp (seq, op, expected) ->
6957 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
6958 let seq, last = get_seq_last seq in
6960 pr " if (! (r %s %d)) {\n" op expected;
6961 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6962 test_name op expected;
6967 List.iter (generate_test_command_call test_name) seq;
6968 generate_test_command_call ~test test_name last
6969 | TestOutputTrue seq ->
6970 pr " /* TestOutputTrue for %s (%d) */\n" name i;
6971 let seq, last = get_seq_last seq in
6974 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6979 List.iter (generate_test_command_call test_name) seq;
6980 generate_test_command_call ~test test_name last
6981 | TestOutputFalse seq ->
6982 pr " /* TestOutputFalse for %s (%d) */\n" name i;
6983 let seq, last = get_seq_last seq in
6986 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6991 List.iter (generate_test_command_call test_name) seq;
6992 generate_test_command_call ~test test_name last
6993 | TestOutputLength (seq, expected) ->
6994 pr " /* TestOutputLength for %s (%d) */\n" name i;
6995 let seq, last = get_seq_last seq in
6998 pr " for (j = 0; j < %d; ++j)\n" expected;
6999 pr " if (r[j] == NULL) {\n";
7000 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7002 pr " print_strings (r);\n";
7005 pr " if (r[j] != NULL) {\n";
7006 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7008 pr " print_strings (r);\n";
7012 List.iter (generate_test_command_call test_name) seq;
7013 generate_test_command_call ~test test_name last
7014 | TestOutputBuffer (seq, expected) ->
7015 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7016 pr " const char *expected = \"%s\";\n" (c_quote expected);
7017 let seq, last = get_seq_last seq in
7018 let len = String.length expected in
7020 pr " if (size != %d) {\n" len;
7021 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7024 pr " if (STRNEQLEN (r, expected, size)) {\n";
7025 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7029 List.iter (generate_test_command_call test_name) seq;
7030 generate_test_command_call ~test test_name last
7031 | TestOutputStruct (seq, checks) ->
7032 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7033 let seq, last = get_seq_last seq in
7037 | CompareWithInt (field, expected) ->
7038 pr " if (r->%s != %d) {\n" field expected;
7039 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7040 test_name field expected;
7041 pr " (int) r->%s);\n" field;
7044 | CompareWithIntOp (field, op, expected) ->
7045 pr " if (!(r->%s %s %d)) {\n" field op expected;
7046 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7047 test_name field op expected;
7048 pr " (int) r->%s);\n" field;
7051 | CompareWithString (field, expected) ->
7052 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7053 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7054 test_name field expected;
7055 pr " r->%s);\n" field;
7058 | CompareFieldsIntEq (field1, field2) ->
7059 pr " if (r->%s != r->%s) {\n" field1 field2;
7060 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7061 test_name field1 field2;
7062 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7065 | CompareFieldsStrEq (field1, field2) ->
7066 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7067 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7068 test_name field1 field2;
7069 pr " r->%s, r->%s);\n" field1 field2;
7074 List.iter (generate_test_command_call test_name) seq;
7075 generate_test_command_call ~test test_name last
7076 | TestLastFail seq ->
7077 pr " /* TestLastFail for %s (%d) */\n" name i;
7078 let seq, last = get_seq_last seq in
7079 List.iter (generate_test_command_call test_name) seq;
7080 generate_test_command_call test_name ~expect_error:true last
7082 (* Generate the code to run a command, leaving the result in 'r'.
7083 * If you expect to get an error then you should set expect_error:true.
7085 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7087 | [] -> assert false
7089 (* Look up the command to find out what args/ret it has. *)
7092 let _, style, _, _, _, _, _ =
7093 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7096 failwithf "%s: in test, command %s was not found" test_name name in
7098 if List.length (snd style) <> List.length args then
7099 failwithf "%s: in test, wrong number of args given to %s"
7106 | OptString n, "NULL" -> ()
7109 | Dev_or_Path n, arg
7111 | OptString n, arg ->
7112 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7116 | FileIn _, _ | FileOut _, _ -> ()
7117 | StringList n, "" | DeviceList n, "" ->
7118 pr " const char *const %s[1] = { NULL };\n" n
7119 | StringList n, arg | DeviceList n, arg ->
7120 let strs = string_split " " arg in
7123 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7125 pr " const char *const %s[] = {\n" n;
7127 fun i _ -> pr " %s_%d,\n" n i
7131 ) (List.combine (snd style) args);
7134 match fst style with
7135 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7136 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7137 | RConstString _ | RConstOptString _ ->
7138 pr " const char *r;\n"; "NULL"
7139 | RString _ -> pr " char *r;\n"; "NULL"
7140 | RStringList _ | RHashtable _ ->
7144 | RStruct (_, typ) ->
7145 pr " struct guestfs_%s *r;\n" typ; "NULL"
7146 | RStructList (_, typ) ->
7147 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7150 pr " size_t size;\n";
7153 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7154 pr " r = guestfs_%s (g" name;
7156 (* Generate the parameters. *)
7159 | OptString _, "NULL" -> pr ", NULL"
7161 | Device n, _ | Dev_or_Path n, _
7165 | FileIn _, arg | FileOut _, arg ->
7166 pr ", \"%s\"" (c_quote arg)
7167 | StringList n, _ | DeviceList n, _ ->
7168 pr ", (char **) %s" n
7171 try int_of_string arg
7172 with Failure "int_of_string" ->
7173 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7177 try Int64.of_string arg
7178 with Failure "int_of_string" ->
7179 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7182 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7183 ) (List.combine (snd style) args);
7185 (match fst style with
7186 | RBufferOut _ -> pr ", &size"
7192 if not expect_error then
7193 pr " if (r == %s)\n" error_code
7195 pr " if (r != %s)\n" error_code;
7198 (* Insert the test code. *)
7204 (match fst style with
7205 | RErr | RInt _ | RInt64 _ | RBool _
7206 | RConstString _ | RConstOptString _ -> ()
7207 | RString _ | RBufferOut _ -> pr " free (r);\n"
7208 | RStringList _ | RHashtable _ ->
7209 pr " for (i = 0; r[i] != NULL; ++i)\n";
7210 pr " free (r[i]);\n";
7212 | RStruct (_, typ) ->
7213 pr " guestfs_free_%s (r);\n" typ
7214 | RStructList (_, typ) ->
7215 pr " guestfs_free_%s_list (r);\n" typ
7221 let str = replace_str str "\r" "\\r" in
7222 let str = replace_str str "\n" "\\n" in
7223 let str = replace_str str "\t" "\\t" in
7224 let str = replace_str str "\000" "\\0" in
7227 (* Generate a lot of different functions for guestfish. *)
7228 and generate_fish_cmds () =
7229 generate_header CStyle GPLv2plus;
7233 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7235 let all_functions_sorted =
7237 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7238 ) all_functions_sorted in
7240 pr "#include <config.h>\n";
7242 pr "#include <stdio.h>\n";
7243 pr "#include <stdlib.h>\n";
7244 pr "#include <string.h>\n";
7245 pr "#include <inttypes.h>\n";
7247 pr "#include <guestfs.h>\n";
7248 pr "#include \"c-ctype.h\"\n";
7249 pr "#include \"full-write.h\"\n";
7250 pr "#include \"xstrtol.h\"\n";
7251 pr "#include \"fish.h\"\n";
7254 (* list_commands function, which implements guestfish -h *)
7255 pr "void list_commands (void)\n";
7257 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7258 pr " list_builtin_commands ();\n";
7260 fun (name, _, _, flags, _, shortdesc, _) ->
7261 let name = replace_char name '_' '-' in
7262 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7264 ) all_functions_sorted;
7265 pr " printf (\" %%s\\n\",";
7266 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7270 (* display_command function, which implements guestfish -h cmd *)
7271 pr "void display_command (const char *cmd)\n";
7274 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7275 let name2 = replace_char name '_' '-' in
7277 try find_map (function FishAlias n -> Some n | _ -> None) flags
7278 with Not_found -> name in
7279 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7281 match snd style with
7285 name2 (String.concat " " (List.map name_of_argt args)) in
7288 if List.mem ProtocolLimitWarning flags then
7289 ("\n\n" ^ protocol_limit_warning)
7292 (* For DangerWillRobinson commands, we should probably have
7293 * guestfish prompt before allowing you to use them (especially
7294 * in interactive mode). XXX
7298 if List.mem DangerWillRobinson flags then
7299 ("\n\n" ^ danger_will_robinson)
7304 match deprecation_notice flags with
7306 | Some txt -> "\n\n" ^ txt in
7308 let describe_alias =
7309 if name <> alias then
7310 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7314 pr "STRCASEEQ (cmd, \"%s\")" name;
7315 if name <> name2 then
7316 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7317 if name <> alias then
7318 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7320 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7322 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7323 "=head1 DESCRIPTION\n\n" ^
7324 longdesc ^ warnings ^ describe_alias);
7327 pr " display_builtin_command (cmd);\n";
7331 let emit_print_list_function typ =
7332 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7335 pr " unsigned int i;\n";
7337 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7338 pr " printf (\"[%%d] = {\\n\", i);\n";
7339 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7340 pr " printf (\"}\\n\");\n";
7346 (* print_* functions *)
7350 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7352 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7355 pr " unsigned int i;\n";
7361 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7363 pr " printf (\"%%s%s: \", indent);\n" name;
7364 pr " for (i = 0; i < 32; ++i)\n";
7365 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7366 pr " printf (\"\\n\");\n"
7368 pr " printf (\"%%s%s: \", indent);\n" name;
7369 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7370 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7371 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7373 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7374 pr " printf (\"\\n\");\n"
7375 | name, (FUInt64|FBytes) ->
7376 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7379 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7382 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7385 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7388 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7390 | name, FOptPercent ->
7391 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7392 typ name name typ name;
7393 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7399 (* Emit a print_TYPE_list function definition only if that function is used. *)
7402 | typ, (RStructListOnly | RStructAndList) ->
7403 (* generate the function for typ *)
7404 emit_print_list_function typ
7405 | typ, _ -> () (* empty *)
7406 ) (rstructs_used_by all_functions);
7408 (* Emit a print_TYPE function definition only if that function is used. *)
7411 | typ, (RStructOnly | RStructAndList) ->
7412 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7414 pr " print_%s_indent (%s, \"\");\n" typ typ;
7417 | typ, _ -> () (* empty *)
7418 ) (rstructs_used_by all_functions);
7420 (* run_<action> actions *)
7422 fun (name, style, _, flags, _, _, _) ->
7423 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7425 (match fst style with
7428 | RBool _ -> pr " int r;\n"
7429 | RInt64 _ -> pr " int64_t r;\n"
7430 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7431 | RString _ -> pr " char *r;\n"
7432 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7433 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7434 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7437 pr " size_t size;\n";
7443 | OptString n -> pr " const char *%s;\n" n
7447 | FileOut n -> pr " char *%s;\n" n
7448 | StringList n | DeviceList n -> pr " char **%s;\n" n
7449 | Bool n -> pr " int %s;\n" n
7450 | Int n -> pr " int %s;\n" n
7451 | Int64 n -> pr " int64_t %s;\n" n
7454 (* Check and convert parameters. *)
7455 let argc_expected = List.length (snd style) in
7456 pr " if (argc != %d) {\n" argc_expected;
7457 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7459 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7463 let parse_integer fn fntyp rtyp range name i =
7465 pr " strtol_error xerr;\n";
7466 pr " %s r;\n" fntyp;
7468 pr " xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7469 pr " if (xerr != LONGINT_OK) {\n";
7470 pr " fprintf (stderr,\n";
7471 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7472 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7477 | Some (min, max, comment) ->
7478 pr " /* %s */\n" comment;
7479 pr " if (r < %s || r > %s) {\n" min max;
7480 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7484 pr " /* The check above should ensure this assignment does not overflow. */\n";
7486 pr " %s = r;\n" name;
7495 pr " %s = argv[%d];\n" name i
7497 | Dev_or_Path name ->
7498 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7499 pr " if (%s == NULL) return -1;\n" name
7501 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7504 pr " %s = file_in (argv[%d]);\n" name i;
7505 pr " if (%s == NULL) return -1;\n" name
7507 pr " %s = file_out (argv[%d]);\n" name i;
7508 pr " if (%s == NULL) return -1;\n" name
7509 | StringList name | DeviceList name ->
7510 pr " %s = parse_string_list (argv[%d]);\n" name i;
7511 pr " if (%s == NULL) return -1;\n" name;
7513 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7516 let min = "(-(2LL<<30))"
7517 and max = "((2LL<<30)-1)"
7519 "The Int type in the generator is a signed 31 bit int." in
7520 Some (min, max, comment) in
7521 parse_integer "xstrtoll" "long long" "int" range name i
7523 parse_integer "xstrtoll" "long long" "int64_t" None name i
7526 (* Call C API function. *)
7528 try find_map (function FishAction n -> Some n | _ -> None) flags
7529 with Not_found -> sprintf "guestfs_%s" name in
7531 generate_c_call_args ~handle:"g" style;
7536 | Device name | String name
7537 | OptString name | Bool name
7538 | Int name | Int64 name -> ()
7539 | Pathname name | Dev_or_Path name | FileOut name ->
7540 pr " free (%s);\n" name
7542 pr " free_file_in (%s);\n" name
7543 | StringList name | DeviceList name ->
7544 pr " free_strings (%s);\n" name
7547 (* Any output flags? *)
7549 let flags = filter_map (
7550 function FishOutput flag -> Some flag | _ -> None
7556 failwithf "%s: more than one FishOutput flag is not allowed" name in
7558 (* Check return value for errors and display command results. *)
7559 (match fst style with
7560 | RErr -> pr " return r;\n"
7562 pr " if (r == -1) return -1;\n";
7563 (match fish_output with
7565 pr " printf (\"%%d\\n\", r);\n";
7566 | Some FishOutputOctal ->
7567 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7568 | Some FishOutputHexadecimal ->
7569 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7572 pr " if (r == -1) return -1;\n";
7573 (match fish_output with
7575 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7576 | Some FishOutputOctal ->
7577 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7578 | Some FishOutputHexadecimal ->
7579 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7582 pr " if (r == -1) return -1;\n";
7583 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7586 pr " if (r == NULL) return -1;\n";
7587 pr " printf (\"%%s\\n\", r);\n";
7589 | RConstOptString _ ->
7590 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7593 pr " if (r == NULL) return -1;\n";
7594 pr " printf (\"%%s\\n\", r);\n";
7598 pr " if (r == NULL) return -1;\n";
7599 pr " print_strings (r);\n";
7600 pr " free_strings (r);\n";
7602 | RStruct (_, typ) ->
7603 pr " if (r == NULL) return -1;\n";
7604 pr " print_%s (r);\n" typ;
7605 pr " guestfs_free_%s (r);\n" typ;
7607 | RStructList (_, typ) ->
7608 pr " if (r == NULL) return -1;\n";
7609 pr " print_%s_list (r);\n" typ;
7610 pr " guestfs_free_%s_list (r);\n" typ;
7613 pr " if (r == NULL) return -1;\n";
7614 pr " print_table (r);\n";
7615 pr " free_strings (r);\n";
7618 pr " if (r == NULL) return -1;\n";
7619 pr " if (full_write (1, r, size) != size) {\n";
7620 pr " perror (\"write\");\n";
7631 (* run_action function *)
7632 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7635 fun (name, _, _, flags, _, _, _) ->
7636 let name2 = replace_char name '_' '-' in
7638 try find_map (function FishAlias n -> Some n | _ -> None) flags
7639 with Not_found -> name in
7641 pr "STRCASEEQ (cmd, \"%s\")" name;
7642 if name <> name2 then
7643 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7644 if name <> alias then
7645 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7647 pr " return run_%s (cmd, argc, argv);\n" name;
7651 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7652 pr " if (command_num == 1)\n";
7653 pr " extended_help_message ();\n";
7660 (* Readline completion for guestfish. *)
7661 and generate_fish_completion () =
7662 generate_header CStyle GPLv2plus;
7666 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7676 #ifdef HAVE_LIBREADLINE
7677 #include <readline/readline.h>
7682 #ifdef HAVE_LIBREADLINE
7684 static const char *const commands[] = {
7685 BUILTIN_COMMANDS_FOR_COMPLETION,
7688 (* Get the commands, including the aliases. They don't need to be
7689 * sorted - the generator() function just does a dumb linear search.
7693 fun (name, _, _, flags, _, _, _) ->
7694 let name2 = replace_char name '_' '-' in
7696 try find_map (function FishAlias n -> Some n | _ -> None) flags
7697 with Not_found -> name in
7699 if name <> alias then [name2; alias] else [name2]
7701 let commands = List.flatten commands in
7703 List.iter (pr " \"%s\",\n") commands;
7709 generator (const char *text, int state)
7711 static int index, len;
7716 len = strlen (text);
7719 rl_attempted_completion_over = 1;
7721 while ((name = commands[index]) != NULL) {
7723 if (STRCASEEQLEN (name, text, len))
7724 return strdup (name);
7730 #endif /* HAVE_LIBREADLINE */
7732 #ifdef HAVE_RL_COMPLETION_MATCHES
7733 #define RL_COMPLETION_MATCHES rl_completion_matches
7735 #ifdef HAVE_COMPLETION_MATCHES
7736 #define RL_COMPLETION_MATCHES completion_matches
7738 #endif /* else just fail if we don't have either symbol */
7741 do_completion (const char *text, int start, int end)
7743 char **matches = NULL;
7745 #ifdef HAVE_LIBREADLINE
7746 rl_completion_append_character = ' ';
7749 matches = RL_COMPLETION_MATCHES (text, generator);
7750 else if (complete_dest_paths)
7751 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7758 (* Generate the POD documentation for guestfish. *)
7759 and generate_fish_actions_pod () =
7760 let all_functions_sorted =
7762 fun (_, _, _, flags, _, _, _) ->
7763 not (List.mem NotInFish flags || List.mem NotInDocs flags)
7764 ) all_functions_sorted in
7766 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7769 fun (name, style, _, flags, _, _, longdesc) ->
7771 Str.global_substitute rex (
7774 try Str.matched_group 1 s
7776 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7777 "C<" ^ replace_char sub '_' '-' ^ ">"
7779 let name = replace_char name '_' '-' in
7781 try find_map (function FishAlias n -> Some n | _ -> None) flags
7782 with Not_found -> name in
7784 pr "=head2 %s" name;
7785 if name <> alias then
7792 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7793 | OptString n -> pr " %s" n
7794 | StringList n | DeviceList n -> pr " '%s ...'" n
7795 | Bool _ -> pr " true|false"
7796 | Int n -> pr " %s" n
7797 | Int64 n -> pr " %s" n
7798 | FileIn n | FileOut n -> pr " (%s|-)" n
7802 pr "%s\n\n" longdesc;
7804 if List.exists (function FileIn _ | FileOut _ -> true
7805 | _ -> false) (snd style) then
7806 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7808 if List.mem ProtocolLimitWarning flags then
7809 pr "%s\n\n" protocol_limit_warning;
7811 if List.mem DangerWillRobinson flags then
7812 pr "%s\n\n" danger_will_robinson;
7814 match deprecation_notice flags with
7816 | Some txt -> pr "%s\n\n" txt
7817 ) all_functions_sorted
7819 (* Generate a C function prototype. *)
7820 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7821 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7823 ?handle name style =
7824 if extern then pr "extern ";
7825 if static then pr "static ";
7826 (match fst style with
7828 | RInt _ -> pr "int "
7829 | RInt64 _ -> pr "int64_t "
7830 | RBool _ -> pr "int "
7831 | RConstString _ | RConstOptString _ -> pr "const char *"
7832 | RString _ | RBufferOut _ -> pr "char *"
7833 | RStringList _ | RHashtable _ -> pr "char **"
7834 | RStruct (_, typ) ->
7835 if not in_daemon then pr "struct guestfs_%s *" typ
7836 else pr "guestfs_int_%s *" typ
7837 | RStructList (_, typ) ->
7838 if not in_daemon then pr "struct guestfs_%s_list *" typ
7839 else pr "guestfs_int_%s_list *" typ
7841 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7842 pr "%s%s (" prefix name;
7843 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7846 let comma = ref false in
7849 | Some handle -> pr "guestfs_h *%s" handle; comma := true
7853 if single_line then pr ", " else pr ",\n\t\t"
7860 | Device n | Dev_or_Path n
7864 pr "const char *%s" n
7865 | StringList n | DeviceList n ->
7867 pr "char *const *%s" n
7868 | Bool n -> next (); pr "int %s" n
7869 | Int n -> next (); pr "int %s" n
7870 | Int64 n -> next (); pr "int64_t %s" n
7873 if not in_daemon then (next (); pr "const char *%s" n)
7875 if is_RBufferOut then (next (); pr "size_t *size_r");
7878 if semicolon then pr ";";
7879 if newline then pr "\n"
7881 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7882 and generate_c_call_args ?handle ?(decl = false) style =
7884 let comma = ref false in
7886 if !comma then pr ", ";
7891 | Some handle -> pr "%s" handle; comma := true
7896 pr "%s" (name_of_argt arg)
7898 (* For RBufferOut calls, add implicit &size parameter. *)
7900 match fst style with
7908 (* Generate the OCaml bindings interface. *)
7909 and generate_ocaml_mli () =
7910 generate_header OCamlStyle LGPLv2plus;
7913 (** For API documentation you should refer to the C API
7914 in the guestfs(3) manual page. The OCaml API uses almost
7915 exactly the same calls. *)
7918 (** A [guestfs_h] handle. *)
7920 exception Error of string
7921 (** This exception is raised when there is an error. *)
7923 exception Handle_closed of string
7924 (** This exception is raised if you use a {!Guestfs.t} handle
7925 after calling {!close} on it. The string is the name of
7928 val create : unit -> t
7929 (** Create a {!Guestfs.t} handle. *)
7931 val close : t -> unit
7932 (** Close the {!Guestfs.t} handle and free up all resources used
7935 Handles are closed by the garbage collector when they become
7936 unreferenced, but callers can call this in order to provide
7937 predictable cleanup. *)
7940 generate_ocaml_structure_decls ();
7944 fun (name, style, _, _, _, shortdesc, _) ->
7945 generate_ocaml_prototype name style;
7946 pr "(** %s *)\n" shortdesc;
7948 ) all_functions_sorted
7950 (* Generate the OCaml bindings implementation. *)
7951 and generate_ocaml_ml () =
7952 generate_header OCamlStyle LGPLv2plus;
7957 exception Error of string
7958 exception Handle_closed of string
7960 external create : unit -> t = \"ocaml_guestfs_create\"
7961 external close : t -> unit = \"ocaml_guestfs_close\"
7963 (* Give the exceptions names, so they can be raised from the C code. *)
7965 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7966 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7970 generate_ocaml_structure_decls ();
7974 fun (name, style, _, _, _, shortdesc, _) ->
7975 generate_ocaml_prototype ~is_external:true name style;
7976 ) all_functions_sorted
7978 (* Generate the OCaml bindings C implementation. *)
7979 and generate_ocaml_c () =
7980 generate_header CStyle LGPLv2plus;
7987 #include <caml/config.h>
7988 #include <caml/alloc.h>
7989 #include <caml/callback.h>
7990 #include <caml/fail.h>
7991 #include <caml/memory.h>
7992 #include <caml/mlvalues.h>
7993 #include <caml/signals.h>
7995 #include <guestfs.h>
7997 #include \"guestfs_c.h\"
7999 /* Copy a hashtable of string pairs into an assoc-list. We return
8000 * the list in reverse order, but hashtables aren't supposed to be
8003 static CAMLprim value
8004 copy_table (char * const * argv)
8007 CAMLlocal5 (rv, pairv, kv, vv, cons);
8011 for (i = 0; argv[i] != NULL; i += 2) {
8012 kv = caml_copy_string (argv[i]);
8013 vv = caml_copy_string (argv[i+1]);
8014 pairv = caml_alloc (2, 0);
8015 Store_field (pairv, 0, kv);
8016 Store_field (pairv, 1, vv);
8017 cons = caml_alloc (2, 0);
8018 Store_field (cons, 1, rv);
8020 Store_field (cons, 0, pairv);
8028 (* Struct copy functions. *)
8030 let emit_ocaml_copy_list_function typ =
8031 pr "static CAMLprim value\n";
8032 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8034 pr " CAMLparam0 ();\n";
8035 pr " CAMLlocal2 (rv, v);\n";
8036 pr " unsigned int i;\n";
8038 pr " if (%ss->len == 0)\n" typ;
8039 pr " CAMLreturn (Atom (0));\n";
8041 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8042 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8043 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8044 pr " caml_modify (&Field (rv, i), v);\n";
8046 pr " CAMLreturn (rv);\n";
8054 let has_optpercent_col =
8055 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8057 pr "static CAMLprim value\n";
8058 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8060 pr " CAMLparam0 ();\n";
8061 if has_optpercent_col then
8062 pr " CAMLlocal3 (rv, v, v2);\n"
8064 pr " CAMLlocal2 (rv, v);\n";
8066 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8071 pr " v = caml_copy_string (%s->%s);\n" typ name
8073 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8074 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8077 pr " v = caml_alloc_string (32);\n";
8078 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8079 | name, (FBytes|FInt64|FUInt64) ->
8080 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8081 | name, (FInt32|FUInt32) ->
8082 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8083 | name, FOptPercent ->
8084 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8085 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8086 pr " v = caml_alloc (1, 0);\n";
8087 pr " Store_field (v, 0, v2);\n";
8088 pr " } else /* None */\n";
8089 pr " v = Val_int (0);\n";
8091 pr " v = Val_int (%s->%s);\n" typ name
8093 pr " Store_field (rv, %d, v);\n" i
8095 pr " CAMLreturn (rv);\n";
8100 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8103 | typ, (RStructListOnly | RStructAndList) ->
8104 (* generate the function for typ *)
8105 emit_ocaml_copy_list_function typ
8106 | typ, _ -> () (* empty *)
8107 ) (rstructs_used_by all_functions);
8111 fun (name, style, _, _, _, _, _) ->
8112 pr "/* Automatically generated wrapper for function\n";
8114 generate_ocaml_prototype name style;
8119 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8121 let needs_extra_vs =
8122 match fst style with RConstOptString _ -> true | _ -> false in
8124 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8125 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8126 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8129 pr "CAMLprim value\n";
8130 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8131 List.iter (pr ", value %s") (List.tl params);
8136 | [p1; p2; p3; p4; p5] ->
8137 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8138 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8139 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8140 pr " CAMLxparam%d (%s);\n"
8141 (List.length rest) (String.concat ", " rest)
8143 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8145 if not needs_extra_vs then
8146 pr " CAMLlocal1 (rv);\n"
8148 pr " CAMLlocal3 (rv, v, v2);\n";
8151 pr " guestfs_h *g = Guestfs_val (gv);\n";
8152 pr " if (g == NULL)\n";
8153 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8159 | Device n | Dev_or_Path n
8163 pr " const char *%s = String_val (%sv);\n" n n
8165 pr " const char *%s =\n" n;
8166 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8168 | StringList n | DeviceList n ->
8169 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8171 pr " int %s = Bool_val (%sv);\n" n n
8173 pr " int %s = Int_val (%sv);\n" n n
8175 pr " int64_t %s = Int64_val (%sv);\n" n n
8178 match fst style with
8179 | RErr -> pr " int r;\n"; "-1"
8180 | RInt _ -> pr " int r;\n"; "-1"
8181 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8182 | RBool _ -> pr " int r;\n"; "-1"
8183 | RConstString _ | RConstOptString _ ->
8184 pr " const char *r;\n"; "NULL"
8185 | RString _ -> pr " char *r;\n"; "NULL"
8190 | RStruct (_, typ) ->
8191 pr " struct guestfs_%s *r;\n" typ; "NULL"
8192 | RStructList (_, typ) ->
8193 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8200 pr " size_t size;\n";
8204 pr " caml_enter_blocking_section ();\n";
8205 pr " r = guestfs_%s " name;
8206 generate_c_call_args ~handle:"g" style;
8208 pr " caml_leave_blocking_section ();\n";
8212 | StringList n | DeviceList n ->
8213 pr " ocaml_guestfs_free_strings (%s);\n" n;
8214 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8215 | Bool _ | Int _ | Int64 _
8216 | FileIn _ | FileOut _ -> ()
8219 pr " if (r == %s)\n" error_code;
8220 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8223 (match fst style with
8224 | RErr -> pr " rv = Val_unit;\n"
8225 | RInt _ -> pr " rv = Val_int (r);\n"
8227 pr " rv = caml_copy_int64 (r);\n"
8228 | RBool _ -> pr " rv = Val_bool (r);\n"
8230 pr " rv = caml_copy_string (r);\n"
8231 | RConstOptString _ ->
8232 pr " if (r) { /* Some string */\n";
8233 pr " v = caml_alloc (1, 0);\n";
8234 pr " v2 = caml_copy_string (r);\n";
8235 pr " Store_field (v, 0, v2);\n";
8236 pr " } else /* None */\n";
8237 pr " v = Val_int (0);\n";
8239 pr " rv = caml_copy_string (r);\n";
8242 pr " rv = caml_copy_string_array ((const char **) r);\n";
8243 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8245 | RStruct (_, typ) ->
8246 pr " rv = copy_%s (r);\n" typ;
8247 pr " guestfs_free_%s (r);\n" typ;
8248 | RStructList (_, typ) ->
8249 pr " rv = copy_%s_list (r);\n" typ;
8250 pr " guestfs_free_%s_list (r);\n" typ;
8252 pr " rv = copy_table (r);\n";
8253 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8256 pr " rv = caml_alloc_string (size);\n";
8257 pr " memcpy (String_val (rv), r, size);\n";
8260 pr " CAMLreturn (rv);\n";
8264 if List.length params > 5 then (
8265 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8266 pr "CAMLprim value ";
8267 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8268 pr "CAMLprim value\n";
8269 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8271 pr " return ocaml_guestfs_%s (argv[0]" name;
8272 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8277 ) all_functions_sorted
8279 and generate_ocaml_structure_decls () =
8282 pr "type %s = {\n" typ;
8285 | name, FString -> pr " %s : string;\n" name
8286 | name, FBuffer -> pr " %s : string;\n" name
8287 | name, FUUID -> pr " %s : string;\n" name
8288 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8289 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8290 | name, FChar -> pr " %s : char;\n" name
8291 | name, FOptPercent -> pr " %s : float option;\n" name
8297 and generate_ocaml_prototype ?(is_external = false) name style =
8298 if is_external then pr "external " else pr "val ";
8299 pr "%s : t -> " name;
8302 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8303 | OptString _ -> pr "string option -> "
8304 | StringList _ | DeviceList _ -> pr "string array -> "
8305 | Bool _ -> pr "bool -> "
8306 | Int _ -> pr "int -> "
8307 | Int64 _ -> pr "int64 -> "
8309 (match fst style with
8310 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8311 | RInt _ -> pr "int"
8312 | RInt64 _ -> pr "int64"
8313 | RBool _ -> pr "bool"
8314 | RConstString _ -> pr "string"
8315 | RConstOptString _ -> pr "string option"
8316 | RString _ | RBufferOut _ -> pr "string"
8317 | RStringList _ -> pr "string array"
8318 | RStruct (_, typ) -> pr "%s" typ
8319 | RStructList (_, typ) -> pr "%s array" typ
8320 | RHashtable _ -> pr "(string * string) list"
8322 if is_external then (
8324 if List.length (snd style) + 1 > 5 then
8325 pr "\"ocaml_guestfs_%s_byte\" " name;
8326 pr "\"ocaml_guestfs_%s\"" name
8330 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8331 and generate_perl_xs () =
8332 generate_header CStyle LGPLv2plus;
8335 #include \"EXTERN.h\"
8339 #include <guestfs.h>
8342 #define PRId64 \"lld\"
8346 my_newSVll(long long val) {
8347 #ifdef USE_64_BIT_ALL
8348 return newSViv(val);
8352 len = snprintf(buf, 100, \"%%\" PRId64, val);
8353 return newSVpv(buf, len);
8358 #define PRIu64 \"llu\"
8362 my_newSVull(unsigned long long val) {
8363 #ifdef USE_64_BIT_ALL
8364 return newSVuv(val);
8368 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8369 return newSVpv(buf, len);
8373 /* http://www.perlmonks.org/?node_id=680842 */
8375 XS_unpack_charPtrPtr (SV *arg) {
8380 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8381 croak (\"array reference expected\");
8383 av = (AV *)SvRV (arg);
8384 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8386 croak (\"malloc failed\");
8388 for (i = 0; i <= av_len (av); i++) {
8389 SV **elem = av_fetch (av, i, 0);
8391 if (!elem || !*elem)
8392 croak (\"missing element in list\");
8394 ret[i] = SvPV_nolen (*elem);
8402 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8409 RETVAL = guestfs_create ();
8411 croak (\"could not create guestfs handle\");
8412 guestfs_set_error_handler (RETVAL, NULL, NULL);
8425 fun (name, style, _, _, _, _, _) ->
8426 (match fst style with
8427 | RErr -> pr "void\n"
8428 | RInt _ -> pr "SV *\n"
8429 | RInt64 _ -> pr "SV *\n"
8430 | RBool _ -> pr "SV *\n"
8431 | RConstString _ -> pr "SV *\n"
8432 | RConstOptString _ -> pr "SV *\n"
8433 | RString _ -> pr "SV *\n"
8434 | RBufferOut _ -> pr "SV *\n"
8436 | RStruct _ | RStructList _
8438 pr "void\n" (* all lists returned implictly on the stack *)
8440 (* Call and arguments. *)
8442 generate_c_call_args ~handle:"g" ~decl:true style;
8444 pr " guestfs_h *g;\n";
8448 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8451 (* http://www.perlmonks.org/?node_id=554277
8452 * Note that the implicit handle argument means we have
8453 * to add 1 to the ST(x) operator.
8455 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8456 | StringList n | DeviceList n -> pr " char **%s;\n" n
8457 | Bool n -> pr " int %s;\n" n
8458 | Int n -> pr " int %s;\n" n
8459 | Int64 n -> pr " int64_t %s;\n" n
8462 let do_cleanups () =
8465 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8466 | Bool _ | Int _ | Int64 _
8467 | FileIn _ | FileOut _ -> ()
8468 | StringList n | DeviceList n -> pr " free (%s);\n" n
8473 (match fst style with
8478 pr " r = guestfs_%s " name;
8479 generate_c_call_args ~handle:"g" style;
8482 pr " if (r == -1)\n";
8483 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8489 pr " %s = guestfs_%s " n name;
8490 generate_c_call_args ~handle:"g" style;
8493 pr " if (%s == -1)\n" n;
8494 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8495 pr " RETVAL = newSViv (%s);\n" n;
8500 pr " int64_t %s;\n" n;
8502 pr " %s = guestfs_%s " n name;
8503 generate_c_call_args ~handle:"g" style;
8506 pr " if (%s == -1)\n" n;
8507 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8508 pr " RETVAL = my_newSVll (%s);\n" n;
8513 pr " const char *%s;\n" n;
8515 pr " %s = guestfs_%s " n name;
8516 generate_c_call_args ~handle:"g" style;
8519 pr " if (%s == NULL)\n" n;
8520 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8521 pr " RETVAL = newSVpv (%s, 0);\n" n;
8524 | RConstOptString n ->
8526 pr " const char *%s;\n" n;
8528 pr " %s = guestfs_%s " n name;
8529 generate_c_call_args ~handle:"g" style;
8532 pr " if (%s == NULL)\n" n;
8533 pr " RETVAL = &PL_sv_undef;\n";
8535 pr " RETVAL = newSVpv (%s, 0);\n" n;
8540 pr " char *%s;\n" n;
8542 pr " %s = guestfs_%s " n name;
8543 generate_c_call_args ~handle:"g" style;
8546 pr " if (%s == NULL)\n" n;
8547 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8548 pr " RETVAL = newSVpv (%s, 0);\n" n;
8549 pr " free (%s);\n" n;
8552 | RStringList n | RHashtable n ->
8554 pr " char **%s;\n" n;
8557 pr " %s = guestfs_%s " n name;
8558 generate_c_call_args ~handle:"g" style;
8561 pr " if (%s == NULL)\n" n;
8562 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8563 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8564 pr " EXTEND (SP, n);\n";
8565 pr " for (i = 0; i < n; ++i) {\n";
8566 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8567 pr " free (%s[i]);\n" n;
8569 pr " free (%s);\n" n;
8570 | RStruct (n, typ) ->
8571 let cols = cols_of_struct typ in
8572 generate_perl_struct_code typ cols name style n do_cleanups
8573 | RStructList (n, typ) ->
8574 let cols = cols_of_struct typ in
8575 generate_perl_struct_list_code typ cols name style n do_cleanups
8578 pr " char *%s;\n" n;
8579 pr " size_t size;\n";
8581 pr " %s = guestfs_%s " n name;
8582 generate_c_call_args ~handle:"g" style;
8585 pr " if (%s == NULL)\n" n;
8586 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8587 pr " RETVAL = newSVpvn (%s, size);\n" n;
8588 pr " free (%s);\n" n;
8596 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8598 pr " struct guestfs_%s_list *%s;\n" typ n;
8602 pr " %s = guestfs_%s " n name;
8603 generate_c_call_args ~handle:"g" style;
8606 pr " if (%s == NULL)\n" n;
8607 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8608 pr " EXTEND (SP, %s->len);\n" n;
8609 pr " for (i = 0; i < %s->len; ++i) {\n" n;
8610 pr " hv = newHV ();\n";
8614 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8615 name (String.length name) n name
8617 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8618 name (String.length name) n name
8620 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8621 name (String.length name) n name n name
8622 | name, (FBytes|FUInt64) ->
8623 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8624 name (String.length name) n name
8626 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8627 name (String.length name) n name
8628 | name, (FInt32|FUInt32) ->
8629 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8630 name (String.length name) n name
8632 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8633 name (String.length name) n name
8634 | name, FOptPercent ->
8635 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8636 name (String.length name) n name
8638 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8640 pr " guestfs_free_%s_list (%s);\n" typ n
8642 and generate_perl_struct_code typ cols name style n do_cleanups =
8644 pr " struct guestfs_%s *%s;\n" typ n;
8646 pr " %s = guestfs_%s " n name;
8647 generate_c_call_args ~handle:"g" style;
8650 pr " if (%s == NULL)\n" n;
8651 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8652 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
8654 fun ((name, _) as col) ->
8655 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8659 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8662 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8665 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8667 | name, (FBytes|FUInt64) ->
8668 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8671 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8673 | name, (FInt32|FUInt32) ->
8674 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8677 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8679 | name, FOptPercent ->
8680 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8683 pr " free (%s);\n" n
8685 (* Generate Sys/Guestfs.pm. *)
8686 and generate_perl_pm () =
8687 generate_header HashStyle LGPLv2plus;
8694 Sys::Guestfs - Perl bindings for libguestfs
8700 my $h = Sys::Guestfs->new ();
8701 $h->add_drive ('guest.img');
8703 $h->mount ('/dev/sda1', '/');
8704 $h->touch ('/hello');
8709 The C<Sys::Guestfs> module provides a Perl XS binding to the
8710 libguestfs API for examining and modifying virtual machine
8713 Amongst the things this is good for: making batch configuration
8714 changes to guests, getting disk used/free statistics (see also:
8715 virt-df), migrating between virtualization systems (see also:
8716 virt-p2v), performing partial backups, performing partial guest
8717 clones, cloning guests and changing registry/UUID/hostname info, and
8720 Libguestfs uses Linux kernel and qemu code, and can access any type of
8721 guest filesystem that Linux and qemu can, including but not limited
8722 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8723 schemes, qcow, qcow2, vmdk.
8725 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8726 LVs, what filesystem is in each LV, etc.). It can also run commands
8727 in the context of the guest. Also you can access filesystems over
8730 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8731 functions for using libguestfs from Perl, including integration
8736 All errors turn into calls to C<croak> (see L<Carp(3)>).
8744 package Sys::Guestfs;
8750 XSLoader::load ('Sys::Guestfs');
8752 =item $h = Sys::Guestfs->new ();
8754 Create a new guestfs handle.
8760 my $class = ref ($proto) || $proto;
8762 my $self = Sys::Guestfs::_create ();
8763 bless $self, $class;
8769 (* Actions. We only need to print documentation for these as
8770 * they are pulled in from the XS code automatically.
8773 fun (name, style, _, flags, _, _, longdesc) ->
8774 if not (List.mem NotInDocs flags) then (
8775 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8777 generate_perl_prototype name style;
8779 pr "%s\n\n" longdesc;
8780 if List.mem ProtocolLimitWarning flags then
8781 pr "%s\n\n" protocol_limit_warning;
8782 if List.mem DangerWillRobinson flags then
8783 pr "%s\n\n" danger_will_robinson;
8784 match deprecation_notice flags with
8786 | Some txt -> pr "%s\n\n" txt
8788 ) all_functions_sorted;
8800 Copyright (C) %s Red Hat Inc.
8804 Please see the file COPYING.LIB for the full license.
8810 L<http://libguestfs.org>,
8811 L<Sys::Guestfs::Lib(3)>.
8816 and generate_perl_prototype name style =
8817 (match fst style with
8825 | RBufferOut n -> pr "$%s = " n
8827 | RHashtable n -> pr "%%%s = " n
8829 | RStructList (n,_) -> pr "@%s = " n
8832 let comma = ref false in
8835 if !comma then pr ", ";
8838 | Pathname n | Device n | Dev_or_Path n | String n
8839 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8841 | StringList n | DeviceList n ->
8846 (* Generate Python C module. *)
8847 and generate_python_c () =
8848 generate_header CStyle LGPLv2plus;
8857 #include \"guestfs.h\"
8865 get_handle (PyObject *obj)
8868 assert (obj != Py_None);
8869 return ((Pyguestfs_Object *) obj)->g;
8873 put_handle (guestfs_h *g)
8877 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8880 /* This list should be freed (but not the strings) after use. */
8882 get_string_list (PyObject *obj)
8889 if (!PyList_Check (obj)) {
8890 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8894 len = PyList_Size (obj);
8895 r = malloc (sizeof (char *) * (len+1));
8897 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8901 for (i = 0; i < len; ++i)
8902 r[i] = PyString_AsString (PyList_GetItem (obj, i));
8909 put_string_list (char * const * const argv)
8914 for (argc = 0; argv[argc] != NULL; ++argc)
8917 list = PyList_New (argc);
8918 for (i = 0; i < argc; ++i)
8919 PyList_SetItem (list, i, PyString_FromString (argv[i]));
8925 put_table (char * const * const argv)
8927 PyObject *list, *item;
8930 for (argc = 0; argv[argc] != NULL; ++argc)
8933 list = PyList_New (argc >> 1);
8934 for (i = 0; i < argc; i += 2) {
8935 item = PyTuple_New (2);
8936 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8937 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8938 PyList_SetItem (list, i >> 1, item);
8945 free_strings (char **argv)
8949 for (argc = 0; argv[argc] != NULL; ++argc)
8955 py_guestfs_create (PyObject *self, PyObject *args)
8959 g = guestfs_create ();
8961 PyErr_SetString (PyExc_RuntimeError,
8962 \"guestfs.create: failed to allocate handle\");
8965 guestfs_set_error_handler (g, NULL, NULL);
8966 return put_handle (g);
8970 py_guestfs_close (PyObject *self, PyObject *args)
8975 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8977 g = get_handle (py_g);
8981 Py_INCREF (Py_None);
8987 let emit_put_list_function typ =
8988 pr "static PyObject *\n";
8989 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8991 pr " PyObject *list;\n";
8994 pr " list = PyList_New (%ss->len);\n" typ;
8995 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
8996 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8997 pr " return list;\n";
9002 (* Structures, turned into Python dictionaries. *)
9005 pr "static PyObject *\n";
9006 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9008 pr " PyObject *dict;\n";
9010 pr " dict = PyDict_New ();\n";
9014 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9015 pr " PyString_FromString (%s->%s));\n"
9018 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9019 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9022 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9023 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9025 | name, (FBytes|FUInt64) ->
9026 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9027 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9030 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9031 pr " PyLong_FromLongLong (%s->%s));\n"
9034 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9035 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9038 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9039 pr " PyLong_FromLong (%s->%s));\n"
9041 | name, FOptPercent ->
9042 pr " if (%s->%s >= 0)\n" typ name;
9043 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9044 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9047 pr " Py_INCREF (Py_None);\n";
9048 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9051 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9052 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9054 pr " return dict;\n";
9060 (* Emit a put_TYPE_list function definition only if that function is used. *)
9063 | typ, (RStructListOnly | RStructAndList) ->
9064 (* generate the function for typ *)
9065 emit_put_list_function typ
9066 | typ, _ -> () (* empty *)
9067 ) (rstructs_used_by all_functions);
9069 (* Python wrapper functions. *)
9071 fun (name, style, _, _, _, _, _) ->
9072 pr "static PyObject *\n";
9073 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9076 pr " PyObject *py_g;\n";
9077 pr " guestfs_h *g;\n";
9078 pr " PyObject *py_r;\n";
9081 match fst style with
9082 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9083 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9084 | RConstString _ | RConstOptString _ ->
9085 pr " const char *r;\n"; "NULL"
9086 | RString _ -> pr " char *r;\n"; "NULL"
9087 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9088 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9089 | RStructList (_, typ) ->
9090 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9093 pr " size_t size;\n";
9098 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9099 pr " const char *%s;\n" n
9100 | OptString n -> pr " const char *%s;\n" n
9101 | StringList n | DeviceList n ->
9102 pr " PyObject *py_%s;\n" n;
9103 pr " char **%s;\n" n
9104 | Bool n -> pr " int %s;\n" n
9105 | Int n -> pr " int %s;\n" n
9106 | Int64 n -> pr " long long %s;\n" n
9111 (* Convert the parameters. *)
9112 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9115 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9116 | OptString _ -> pr "z"
9117 | StringList _ | DeviceList _ -> pr "O"
9118 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9120 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9121 * emulate C's int/long/long long in Python?
9124 pr ":guestfs_%s\",\n" name;
9128 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9129 | OptString n -> pr ", &%s" n
9130 | StringList n | DeviceList n -> pr ", &py_%s" n
9131 | Bool n -> pr ", &%s" n
9132 | Int n -> pr ", &%s" n
9133 | Int64 n -> pr ", &%s" n
9137 pr " return NULL;\n";
9139 pr " g = get_handle (py_g);\n";
9142 | Pathname _ | Device _ | Dev_or_Path _ | String _
9143 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9144 | StringList n | DeviceList n ->
9145 pr " %s = get_string_list (py_%s);\n" n n;
9146 pr " if (!%s) return NULL;\n" n
9151 pr " r = guestfs_%s " name;
9152 generate_c_call_args ~handle:"g" style;
9157 | Pathname _ | Device _ | Dev_or_Path _ | String _
9158 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9159 | StringList n | DeviceList n ->
9160 pr " free (%s);\n" n
9163 pr " if (r == %s) {\n" error_code;
9164 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9165 pr " return NULL;\n";
9169 (match fst style with
9171 pr " Py_INCREF (Py_None);\n";
9172 pr " py_r = Py_None;\n"
9174 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9175 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9176 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9177 | RConstOptString _ ->
9179 pr " py_r = PyString_FromString (r);\n";
9181 pr " Py_INCREF (Py_None);\n";
9182 pr " py_r = Py_None;\n";
9185 pr " py_r = PyString_FromString (r);\n";
9188 pr " py_r = put_string_list (r);\n";
9189 pr " free_strings (r);\n"
9190 | RStruct (_, typ) ->
9191 pr " py_r = put_%s (r);\n" typ;
9192 pr " guestfs_free_%s (r);\n" typ
9193 | RStructList (_, typ) ->
9194 pr " py_r = put_%s_list (r);\n" typ;
9195 pr " guestfs_free_%s_list (r);\n" typ
9197 pr " py_r = put_table (r);\n";
9198 pr " free_strings (r);\n"
9200 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9204 pr " return py_r;\n";
9209 (* Table of functions. *)
9210 pr "static PyMethodDef methods[] = {\n";
9211 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9212 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9214 fun (name, _, _, _, _, _, _) ->
9215 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9218 pr " { NULL, NULL, 0, NULL }\n";
9222 (* Init function. *)
9225 initlibguestfsmod (void)
9227 static int initialized = 0;
9229 if (initialized) return;
9230 Py_InitModule ((char *) \"libguestfsmod\", methods);
9235 (* Generate Python module. *)
9236 and generate_python_py () =
9237 generate_header HashStyle LGPLv2plus;
9240 u\"\"\"Python bindings for libguestfs
9243 g = guestfs.GuestFS ()
9244 g.add_drive (\"guest.img\")
9246 parts = g.list_partitions ()
9248 The guestfs module provides a Python binding to the libguestfs API
9249 for examining and modifying virtual machine disk images.
9251 Amongst the things this is good for: making batch configuration
9252 changes to guests, getting disk used/free statistics (see also:
9253 virt-df), migrating between virtualization systems (see also:
9254 virt-p2v), performing partial backups, performing partial guest
9255 clones, cloning guests and changing registry/UUID/hostname info, and
9258 Libguestfs uses Linux kernel and qemu code, and can access any type of
9259 guest filesystem that Linux and qemu can, including but not limited
9260 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9261 schemes, qcow, qcow2, vmdk.
9263 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9264 LVs, what filesystem is in each LV, etc.). It can also run commands
9265 in the context of the guest. Also you can access filesystems over
9268 Errors which happen while using the API are turned into Python
9269 RuntimeError exceptions.
9271 To create a guestfs handle you usually have to perform the following
9274 # Create the handle, call add_drive at least once, and possibly
9275 # several times if the guest has multiple block devices:
9276 g = guestfs.GuestFS ()
9277 g.add_drive (\"guest.img\")
9279 # Launch the qemu subprocess and wait for it to become ready:
9282 # Now you can issue commands, for example:
9287 import libguestfsmod
9290 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9292 def __init__ (self):
9293 \"\"\"Create a new libguestfs handle.\"\"\"
9294 self._o = libguestfsmod.create ()
9297 libguestfsmod.close (self._o)
9302 fun (name, style, _, flags, _, _, longdesc) ->
9304 generate_py_call_args ~handle:"self" (snd style);
9307 if not (List.mem NotInDocs flags) then (
9308 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9310 match fst style with
9311 | RErr | RInt _ | RInt64 _ | RBool _
9312 | RConstOptString _ | RConstString _
9313 | RString _ | RBufferOut _ -> doc
9315 doc ^ "\n\nThis function returns a list of strings."
9316 | RStruct (_, typ) ->
9317 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9318 | RStructList (_, typ) ->
9319 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9321 doc ^ "\n\nThis function returns a dictionary." in
9323 if List.mem ProtocolLimitWarning flags then
9324 doc ^ "\n\n" ^ protocol_limit_warning
9327 if List.mem DangerWillRobinson flags then
9328 doc ^ "\n\n" ^ danger_will_robinson
9331 match deprecation_notice flags with
9333 | Some txt -> doc ^ "\n\n" ^ txt in
9334 let doc = pod2text ~width:60 name doc in
9335 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9336 let doc = String.concat "\n " doc in
9337 pr " u\"\"\"%s\"\"\"\n" doc;
9339 pr " return libguestfsmod.%s " name;
9340 generate_py_call_args ~handle:"self._o" (snd style);
9345 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9346 and generate_py_call_args ~handle args =
9348 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9351 (* Useful if you need the longdesc POD text as plain text. Returns a
9354 * Because this is very slow (the slowest part of autogeneration),
9355 * we memoize the results.
9357 and pod2text ~width name longdesc =
9358 let key = width, name, longdesc in
9359 try Hashtbl.find pod2text_memo key
9361 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9362 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9364 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9365 let chan = open_process_in cmd in
9366 let lines = ref [] in
9368 let line = input_line chan in
9369 if i = 1 then (* discard the first line of output *)
9372 let line = triml line in
9373 lines := line :: !lines;
9376 let lines = try loop 1 with End_of_file -> List.rev !lines in
9378 (match close_process_in chan with
9381 failwithf "pod2text: process exited with non-zero status (%d)" i
9382 | WSIGNALED i | WSTOPPED i ->
9383 failwithf "pod2text: process signalled or stopped by signal %d" i
9385 Hashtbl.add pod2text_memo key lines;
9386 pod2text_memo_updated ();
9389 (* Generate ruby bindings. *)
9390 and generate_ruby_c () =
9391 generate_header CStyle LGPLv2plus;
9399 #include \"guestfs.h\"
9401 #include \"extconf.h\"
9403 /* For Ruby < 1.9 */
9405 #define RARRAY_LEN(r) (RARRAY((r))->len)
9408 static VALUE m_guestfs; /* guestfs module */
9409 static VALUE c_guestfs; /* guestfs_h handle */
9410 static VALUE e_Error; /* used for all errors */
9412 static void ruby_guestfs_free (void *p)
9415 guestfs_close ((guestfs_h *) p);
9418 static VALUE ruby_guestfs_create (VALUE m)
9422 g = guestfs_create ();
9424 rb_raise (e_Error, \"failed to create guestfs handle\");
9426 /* Don't print error messages to stderr by default. */
9427 guestfs_set_error_handler (g, NULL, NULL);
9429 /* Wrap it, and make sure the close function is called when the
9432 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9435 static VALUE ruby_guestfs_close (VALUE gv)
9438 Data_Get_Struct (gv, guestfs_h, g);
9440 ruby_guestfs_free (g);
9441 DATA_PTR (gv) = NULL;
9449 fun (name, style, _, _, _, _, _) ->
9450 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9451 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9454 pr " guestfs_h *g;\n";
9455 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9457 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9463 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9464 pr " Check_Type (%sv, T_STRING);\n" n;
9465 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9467 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9468 pr " \"%s\", \"%s\");\n" n name
9470 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9471 | StringList n | DeviceList n ->
9472 pr " char **%s;\n" n;
9473 pr " Check_Type (%sv, T_ARRAY);\n" n;
9475 pr " int i, len;\n";
9476 pr " len = RARRAY_LEN (%sv);\n" n;
9477 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9479 pr " for (i = 0; i < len; ++i) {\n";
9480 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9481 pr " %s[i] = StringValueCStr (v);\n" n;
9483 pr " %s[len] = NULL;\n" n;
9486 pr " int %s = RTEST (%sv);\n" n n
9488 pr " int %s = NUM2INT (%sv);\n" n n
9490 pr " long long %s = NUM2LL (%sv);\n" n n
9495 match fst style with
9496 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9497 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9498 | RConstString _ | RConstOptString _ ->
9499 pr " const char *r;\n"; "NULL"
9500 | RString _ -> pr " char *r;\n"; "NULL"
9501 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9502 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9503 | RStructList (_, typ) ->
9504 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9507 pr " size_t size;\n";
9511 pr " r = guestfs_%s " name;
9512 generate_c_call_args ~handle:"g" style;
9517 | Pathname _ | Device _ | Dev_or_Path _ | String _
9518 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9519 | StringList n | DeviceList n ->
9520 pr " free (%s);\n" n
9523 pr " if (r == %s)\n" error_code;
9524 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9527 (match fst style with
9529 pr " return Qnil;\n"
9530 | RInt _ | RBool _ ->
9531 pr " return INT2NUM (r);\n"
9533 pr " return ULL2NUM (r);\n"
9535 pr " return rb_str_new2 (r);\n";
9536 | RConstOptString _ ->
9538 pr " return rb_str_new2 (r);\n";
9540 pr " return Qnil;\n";
9542 pr " VALUE rv = rb_str_new2 (r);\n";
9546 pr " int i, len = 0;\n";
9547 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
9548 pr " VALUE rv = rb_ary_new2 (len);\n";
9549 pr " for (i = 0; r[i] != NULL; ++i) {\n";
9550 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9551 pr " free (r[i]);\n";
9555 | RStruct (_, typ) ->
9556 let cols = cols_of_struct typ in
9557 generate_ruby_struct_code typ cols
9558 | RStructList (_, typ) ->
9559 let cols = cols_of_struct typ in
9560 generate_ruby_struct_list_code typ cols
9562 pr " VALUE rv = rb_hash_new ();\n";
9564 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
9565 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9566 pr " free (r[i]);\n";
9567 pr " free (r[i+1]);\n";
9572 pr " VALUE rv = rb_str_new (r, size);\n";
9582 /* Initialize the module. */
9583 void Init__guestfs ()
9585 m_guestfs = rb_define_module (\"Guestfs\");
9586 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9587 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9589 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9590 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9593 (* Define the rest of the methods. *)
9595 fun (name, style, _, _, _, _, _) ->
9596 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
9597 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9602 (* Ruby code to return a struct. *)
9603 and generate_ruby_struct_code typ cols =
9604 pr " VALUE rv = rb_hash_new ();\n";
9608 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9610 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9612 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9613 | name, (FBytes|FUInt64) ->
9614 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9616 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9618 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9620 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9621 | name, FOptPercent ->
9622 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9623 | name, FChar -> (* XXX wrong? *)
9624 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9626 pr " guestfs_free_%s (r);\n" typ;
9629 (* Ruby code to return a struct list. *)
9630 and generate_ruby_struct_list_code typ cols =
9631 pr " VALUE rv = rb_ary_new2 (r->len);\n";
9633 pr " for (i = 0; i < r->len; ++i) {\n";
9634 pr " VALUE hv = rb_hash_new ();\n";
9638 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9640 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
9642 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9643 | name, (FBytes|FUInt64) ->
9644 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9646 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9648 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9650 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9651 | name, FOptPercent ->
9652 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9653 | name, FChar -> (* XXX wrong? *)
9654 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9656 pr " rb_ary_push (rv, hv);\n";
9658 pr " guestfs_free_%s_list (r);\n" typ;
9661 (* Generate Java bindings GuestFS.java file. *)
9662 and generate_java_java () =
9663 generate_header CStyle LGPLv2plus;
9666 package com.redhat.et.libguestfs;
9668 import java.util.HashMap;
9669 import com.redhat.et.libguestfs.LibGuestFSException;
9670 import com.redhat.et.libguestfs.PV;
9671 import com.redhat.et.libguestfs.VG;
9672 import com.redhat.et.libguestfs.LV;
9673 import com.redhat.et.libguestfs.Stat;
9674 import com.redhat.et.libguestfs.StatVFS;
9675 import com.redhat.et.libguestfs.IntBool;
9676 import com.redhat.et.libguestfs.Dirent;
9679 * The GuestFS object is a libguestfs handle.
9683 public class GuestFS {
9684 // Load the native code.
9686 System.loadLibrary (\"guestfs_jni\");
9690 * The native guestfs_h pointer.
9695 * Create a libguestfs handle.
9697 * @throws LibGuestFSException
9699 public GuestFS () throws LibGuestFSException
9703 private native long _create () throws LibGuestFSException;
9706 * Close a libguestfs handle.
9708 * You can also leave handles to be collected by the garbage
9709 * collector, but this method ensures that the resources used
9710 * by the handle are freed up immediately. If you call any
9711 * other methods after closing the handle, you will get an
9714 * @throws LibGuestFSException
9716 public void close () throws LibGuestFSException
9722 private native void _close (long g) throws LibGuestFSException;
9724 public void finalize () throws LibGuestFSException
9732 fun (name, style, _, flags, _, shortdesc, longdesc) ->
9733 if not (List.mem NotInDocs flags); then (
9734 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9736 if List.mem ProtocolLimitWarning flags then
9737 doc ^ "\n\n" ^ protocol_limit_warning
9740 if List.mem DangerWillRobinson flags then
9741 doc ^ "\n\n" ^ danger_will_robinson
9744 match deprecation_notice flags with
9746 | Some txt -> doc ^ "\n\n" ^ txt in
9747 let doc = pod2text ~width:60 name doc in
9748 let doc = List.map ( (* RHBZ#501883 *)
9751 | nonempty -> nonempty
9753 let doc = String.concat "\n * " doc in
9756 pr " * %s\n" shortdesc;
9759 pr " * @throws LibGuestFSException\n";
9763 generate_java_prototype ~public:true ~semicolon:false name style;
9766 pr " if (g == 0)\n";
9767 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
9770 if fst style <> RErr then pr "return ";
9772 generate_java_call_args ~handle:"g" (snd style);
9776 generate_java_prototype ~privat:true ~native:true name style;
9783 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9784 and generate_java_call_args ~handle args =
9786 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9789 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9790 ?(semicolon=true) name style =
9791 if privat then pr "private ";
9792 if public then pr "public ";
9793 if native then pr "native ";
9796 (match fst style with
9797 | RErr -> pr "void ";
9798 | RInt _ -> pr "int ";
9799 | RInt64 _ -> pr "long ";
9800 | RBool _ -> pr "boolean ";
9801 | RConstString _ | RConstOptString _ | RString _
9802 | RBufferOut _ -> pr "String ";
9803 | RStringList _ -> pr "String[] ";
9804 | RStruct (_, typ) ->
9805 let name = java_name_of_struct typ in
9807 | RStructList (_, typ) ->
9808 let name = java_name_of_struct typ in
9810 | RHashtable _ -> pr "HashMap<String,String> ";
9813 if native then pr "_%s " name else pr "%s " name;
9815 let needs_comma = ref false in
9824 if !needs_comma then pr ", ";
9825 needs_comma := true;
9829 | Device n | Dev_or_Path n
9835 | StringList n | DeviceList n ->
9846 pr " throws LibGuestFSException";
9847 if semicolon then pr ";"
9849 and generate_java_struct jtyp cols () =
9850 generate_header CStyle LGPLv2plus;
9853 package com.redhat.et.libguestfs;
9856 * Libguestfs %s structure.
9868 | name, FBuffer -> pr " public String %s;\n" name
9869 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
9870 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
9871 | name, FChar -> pr " public char %s;\n" name
9872 | name, FOptPercent ->
9873 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
9874 pr " public float %s;\n" name
9879 and generate_java_c () =
9880 generate_header CStyle LGPLv2plus;
9887 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9888 #include \"guestfs.h\"
9890 /* Note that this function returns. The exception is not thrown
9891 * until after the wrapper function returns.
9894 throw_exception (JNIEnv *env, const char *msg)
9897 cl = (*env)->FindClass (env,
9898 \"com/redhat/et/libguestfs/LibGuestFSException\");
9899 (*env)->ThrowNew (env, cl, msg);
9902 JNIEXPORT jlong JNICALL
9903 Java_com_redhat_et_libguestfs_GuestFS__1create
9904 (JNIEnv *env, jobject obj)
9908 g = guestfs_create ();
9910 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9913 guestfs_set_error_handler (g, NULL, NULL);
9914 return (jlong) (long) g;
9917 JNIEXPORT void JNICALL
9918 Java_com_redhat_et_libguestfs_GuestFS__1close
9919 (JNIEnv *env, jobject obj, jlong jg)
9921 guestfs_h *g = (guestfs_h *) (long) jg;
9928 fun (name, style, _, _, _, _, _) ->
9930 (match fst style with
9931 | RErr -> pr "void ";
9932 | RInt _ -> pr "jint ";
9933 | RInt64 _ -> pr "jlong ";
9934 | RBool _ -> pr "jboolean ";
9935 | RConstString _ | RConstOptString _ | RString _
9936 | RBufferOut _ -> pr "jstring ";
9937 | RStruct _ | RHashtable _ ->
9939 | RStringList _ | RStructList _ ->
9943 pr "Java_com_redhat_et_libguestfs_GuestFS_";
9944 pr "%s" (replace_str ("_" ^ name) "_" "_1");
9946 pr " (JNIEnv *env, jobject obj, jlong jg";
9950 | Device n | Dev_or_Path n
9955 pr ", jstring j%s" n
9956 | StringList n | DeviceList n ->
9957 pr ", jobjectArray j%s" n
9959 pr ", jboolean j%s" n
9967 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
9968 let error_code, no_ret =
9969 match fst style with
9970 | RErr -> pr " int r;\n"; "-1", ""
9972 | RInt _ -> pr " int r;\n"; "-1", "0"
9973 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
9974 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
9975 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
9977 pr " jstring jr;\n";
9978 pr " char *r;\n"; "NULL", "NULL"
9980 pr " jobjectArray jr;\n";
9983 pr " jstring jstr;\n";
9984 pr " char **r;\n"; "NULL", "NULL"
9985 | RStruct (_, typ) ->
9986 pr " jobject jr;\n";
9988 pr " jfieldID fl;\n";
9989 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9990 | RStructList (_, typ) ->
9991 pr " jobjectArray jr;\n";
9993 pr " jfieldID fl;\n";
9994 pr " jobject jfl;\n";
9995 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9996 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
9998 pr " jstring jr;\n";
10000 pr " size_t size;\n";
10005 | Device n | Dev_or_Path n
10010 pr " const char *%s;\n" n
10011 | StringList n | DeviceList n ->
10012 pr " int %s_len;\n" n;
10013 pr " const char **%s;\n" n
10018 pr " int64_t %s;\n" n
10022 (match fst style with
10023 | RStringList _ | RStructList _ -> true
10024 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10025 | RConstOptString _
10026 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10027 List.exists (function
10028 | StringList _ -> true
10029 | DeviceList _ -> true
10030 | _ -> false) (snd style) in
10036 (* Get the parameters. *)
10040 | Device n | Dev_or_Path n
10044 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10046 (* This is completely undocumented, but Java null becomes
10047 * a NULL parameter.
10049 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10050 | StringList n | DeviceList n ->
10051 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10052 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10053 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10054 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10056 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10058 pr " %s[%s_len] = NULL;\n" n n;
10062 pr " %s = j%s;\n" n n
10065 (* Make the call. *)
10066 pr " r = guestfs_%s " name;
10067 generate_c_call_args ~handle:"g" style;
10070 (* Release the parameters. *)
10074 | Device n | Dev_or_Path n
10078 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10080 pr " if (j%s)\n" n;
10081 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10082 | StringList n | DeviceList n ->
10083 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10084 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10086 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10088 pr " free (%s);\n" n
10094 (* Check for errors. *)
10095 pr " if (r == %s) {\n" error_code;
10096 pr " throw_exception (env, guestfs_last_error (g));\n";
10097 pr " return %s;\n" no_ret;
10100 (* Return value. *)
10101 (match fst style with
10103 | RInt _ -> pr " return (jint) r;\n"
10104 | RBool _ -> pr " return (jboolean) r;\n"
10105 | RInt64 _ -> pr " return (jlong) r;\n"
10106 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10107 | RConstOptString _ ->
10108 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10110 pr " jr = (*env)->NewStringUTF (env, r);\n";
10114 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10115 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10116 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10117 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10118 pr " for (i = 0; i < r_len; ++i) {\n";
10119 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10120 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10121 pr " free (r[i]);\n";
10125 | RStruct (_, typ) ->
10126 let jtyp = java_name_of_struct typ in
10127 let cols = cols_of_struct typ in
10128 generate_java_struct_return typ jtyp cols
10129 | RStructList (_, typ) ->
10130 let jtyp = java_name_of_struct typ in
10131 let cols = cols_of_struct typ in
10132 generate_java_struct_list_return typ jtyp cols
10135 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10136 pr " return NULL;\n"
10138 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10147 and generate_java_struct_return typ jtyp cols =
10148 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10149 pr " jr = (*env)->AllocObject (env, cl);\n";
10153 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10154 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10157 pr " char s[33];\n";
10158 pr " memcpy (s, r->%s, 32);\n" name;
10159 pr " s[32] = 0;\n";
10160 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10161 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10165 pr " int len = r->%s_len;\n" name;
10166 pr " char s[len+1];\n";
10167 pr " memcpy (s, r->%s, len);\n" name;
10168 pr " s[len] = 0;\n";
10169 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10170 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10172 | name, (FBytes|FUInt64|FInt64) ->
10173 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10174 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10175 | name, (FUInt32|FInt32) ->
10176 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10177 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10178 | name, FOptPercent ->
10179 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10180 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10182 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10183 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10188 and generate_java_struct_list_return typ jtyp cols =
10189 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10190 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10191 pr " for (i = 0; i < r->len; ++i) {\n";
10192 pr " jfl = (*env)->AllocObject (env, cl);\n";
10196 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10197 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10200 pr " char s[33];\n";
10201 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10202 pr " s[32] = 0;\n";
10203 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10204 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10208 pr " int len = r->val[i].%s_len;\n" name;
10209 pr " char s[len+1];\n";
10210 pr " memcpy (s, r->val[i].%s, len);\n" name;
10211 pr " s[len] = 0;\n";
10212 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10213 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10215 | name, (FBytes|FUInt64|FInt64) ->
10216 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10217 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10218 | name, (FUInt32|FInt32) ->
10219 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10220 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10221 | name, FOptPercent ->
10222 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10223 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10225 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10226 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10228 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10230 pr " guestfs_free_%s_list (r);\n" typ;
10233 and generate_java_makefile_inc () =
10234 generate_header HashStyle GPLv2plus;
10236 pr "java_built_sources = \\\n";
10239 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10241 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10243 and generate_haskell_hs () =
10244 generate_header HaskellStyle LGPLv2plus;
10246 (* XXX We only know how to generate partial FFI for Haskell
10247 * at the moment. Please help out!
10249 let can_generate style =
10253 | RInt64 _, _ -> true
10255 | RConstString _, _
10256 | RConstOptString _, _
10262 | RBufferOut _, _ -> false in
10265 {-# INCLUDE <guestfs.h> #-}
10266 {-# LANGUAGE ForeignFunctionInterface #-}
10271 (* List out the names of the actions we want to export. *)
10273 fun (name, style, _, _, _, _, _) ->
10274 if can_generate style then pr ",\n %s" name
10280 -- Unfortunately some symbols duplicate ones already present
10281 -- in Prelude. We don't know which, so we hard-code a list
10283 import Prelude hiding (truncate)
10287 import Foreign.C.Types
10289 import Control.Exception
10290 import Data.Typeable
10292 data GuestfsS = GuestfsS -- represents the opaque C struct
10293 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10294 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10296 -- XXX define properly later XXX
10300 data IntBool = IntBool
10302 data StatVFS = StatVFS
10303 data Hashtable = Hashtable
10305 foreign import ccall unsafe \"guestfs_create\" c_create
10307 foreign import ccall unsafe \"&guestfs_close\" c_close
10308 :: FunPtr (GuestfsP -> IO ())
10309 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10310 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10312 create :: IO GuestfsH
10315 c_set_error_handler p nullPtr nullPtr
10316 h <- newForeignPtr c_close p
10319 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10320 :: GuestfsP -> IO CString
10322 -- last_error :: GuestfsH -> IO (Maybe String)
10323 -- last_error h = do
10324 -- str <- withForeignPtr h (\\p -> c_last_error p)
10325 -- maybePeek peekCString str
10327 last_error :: GuestfsH -> IO (String)
10329 str <- withForeignPtr h (\\p -> c_last_error p)
10330 if (str == nullPtr)
10331 then return \"no error\"
10332 else peekCString str
10336 (* Generate wrappers for each foreign function. *)
10338 fun (name, style, _, _, _, _, _) ->
10339 if can_generate style then (
10340 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10342 generate_haskell_prototype ~handle:"GuestfsP" style;
10346 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10348 pr "%s %s = do\n" name
10349 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10351 (* Convert pointer arguments using with* functions. *)
10356 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10357 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10358 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10359 | Bool _ | Int _ | Int64 _ -> ()
10361 (* Convert integer arguments. *)
10365 | Bool n -> sprintf "(fromBool %s)" n
10366 | Int n -> sprintf "(fromIntegral %s)" n
10367 | Int64 n -> sprintf "(fromIntegral %s)" n
10368 | FileIn n | FileOut n
10369 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10371 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10372 (String.concat " " ("p" :: args));
10373 (match fst style with
10374 | RErr | RInt _ | RInt64 _ | RBool _ ->
10375 pr " if (r == -1)\n";
10377 pr " err <- last_error h\n";
10379 | RConstString _ | RConstOptString _ | RString _
10380 | RStringList _ | RStruct _
10381 | RStructList _ | RHashtable _ | RBufferOut _ ->
10382 pr " if (r == nullPtr)\n";
10384 pr " err <- last_error h\n";
10387 (match fst style with
10389 pr " else return ()\n"
10391 pr " else return (fromIntegral r)\n"
10393 pr " else return (fromIntegral r)\n"
10395 pr " else return (toBool r)\n"
10397 | RConstOptString _
10404 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10410 and generate_haskell_prototype ~handle ?(hs = false) style =
10411 pr "%s -> " handle;
10412 let string = if hs then "String" else "CString" in
10413 let int = if hs then "Int" else "CInt" in
10414 let bool = if hs then "Bool" else "CInt" in
10415 let int64 = if hs then "Integer" else "Int64" in
10419 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10420 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10421 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10422 | Bool _ -> pr "%s" bool
10423 | Int _ -> pr "%s" int
10424 | Int64 _ -> pr "%s" int
10425 | FileIn _ -> pr "%s" string
10426 | FileOut _ -> pr "%s" string
10431 (match fst style with
10432 | RErr -> if not hs then pr "CInt"
10433 | RInt _ -> pr "%s" int
10434 | RInt64 _ -> pr "%s" int64
10435 | RBool _ -> pr "%s" bool
10436 | RConstString _ -> pr "%s" string
10437 | RConstOptString _ -> pr "Maybe %s" string
10438 | RString _ -> pr "%s" string
10439 | RStringList _ -> pr "[%s]" string
10440 | RStruct (_, typ) ->
10441 let name = java_name_of_struct typ in
10443 | RStructList (_, typ) ->
10444 let name = java_name_of_struct typ in
10446 | RHashtable _ -> pr "Hashtable"
10447 | RBufferOut _ -> pr "%s" string
10451 and generate_csharp () =
10452 generate_header CPlusPlusStyle LGPLv2plus;
10454 (* XXX Make this configurable by the C# assembly users. *)
10455 let library = "libguestfs.so.0" in
10458 // These C# bindings are highly experimental at present.
10460 // Firstly they only work on Linux (ie. Mono). In order to get them
10461 // to work on Windows (ie. .Net) you would need to port the library
10462 // itself to Windows first.
10464 // The second issue is that some calls are known to be incorrect and
10465 // can cause Mono to segfault. Particularly: calls which pass or
10466 // return string[], or return any structure value. This is because
10467 // we haven't worked out the correct way to do this from C#.
10469 // The third issue is that when compiling you get a lot of warnings.
10470 // We are not sure whether the warnings are important or not.
10472 // Fourthly we do not routinely build or test these bindings as part
10473 // of the make && make check cycle, which means that regressions might
10476 // Suggestions and patches are welcome.
10480 // gmcs Libguestfs.cs
10481 // mono Libguestfs.exe
10483 // (You'll probably want to add a Test class / static main function
10484 // otherwise this won't do anything useful).
10488 using System.Runtime.InteropServices;
10489 using System.Runtime.Serialization;
10490 using System.Collections;
10494 class Error : System.ApplicationException
10496 public Error (string message) : base (message) {}
10497 protected Error (SerializationInfo info, StreamingContext context) {}
10504 [DllImport (\"%s\")]
10505 static extern IntPtr guestfs_create ();
10509 _handle = guestfs_create ();
10510 if (_handle == IntPtr.Zero)
10511 throw new Error (\"could not create guestfs handle\");
10514 [DllImport (\"%s\")]
10515 static extern void guestfs_close (IntPtr h);
10519 guestfs_close (_handle);
10522 [DllImport (\"%s\")]
10523 static extern string guestfs_last_error (IntPtr h);
10525 " library library library;
10527 (* Generate C# structure bindings. We prefix struct names with
10528 * underscore because C# cannot have conflicting struct names and
10529 * method names (eg. "class stat" and "stat").
10533 pr " [StructLayout (LayoutKind.Sequential)]\n";
10534 pr " public class _%s {\n" typ;
10537 | name, FChar -> pr " char %s;\n" name
10538 | name, FString -> pr " string %s;\n" name
10540 pr " uint %s_len;\n" name;
10541 pr " string %s;\n" name
10543 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10544 pr " string %s;\n" name
10545 | name, FUInt32 -> pr " uint %s;\n" name
10546 | name, FInt32 -> pr " int %s;\n" name
10547 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
10548 | name, FInt64 -> pr " long %s;\n" name
10549 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
10555 (* Generate C# function bindings. *)
10557 fun (name, style, _, _, _, shortdesc, _) ->
10558 let rec csharp_return_type () =
10559 match fst style with
10561 | RBool n -> "bool"
10563 | RInt64 n -> "long"
10565 | RConstOptString n
10567 | RBufferOut n -> "string"
10568 | RStruct (_,n) -> "_" ^ n
10569 | RHashtable n -> "Hashtable"
10570 | RStringList n -> "string[]"
10571 | RStructList (_,n) -> sprintf "_%s[]" n
10573 and c_return_type () =
10574 match fst style with
10578 | RInt64 _ -> "long"
10580 | RConstOptString _
10582 | RBufferOut _ -> "string"
10583 | RStruct (_,n) -> "_" ^ n
10585 | RStringList _ -> "string[]"
10586 | RStructList (_,n) -> sprintf "_%s[]" n
10588 and c_error_comparison () =
10589 match fst style with
10593 | RInt64 _ -> "== -1"
10595 | RConstOptString _
10601 | RStructList (_,_) -> "== null"
10603 and generate_extern_prototype () =
10604 pr " static extern %s guestfs_%s (IntPtr h"
10605 (c_return_type ()) name;
10608 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10609 | FileIn n | FileOut n ->
10610 pr ", [In] string %s" n
10611 | StringList n | DeviceList n ->
10612 pr ", [In] string[] %s" n
10622 and generate_public_prototype () =
10623 pr " public %s %s (" (csharp_return_type ()) name;
10624 let comma = ref false in
10626 if !comma then pr ", ";
10631 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10632 | FileIn n | FileOut n ->
10633 next (); pr "string %s" n
10634 | StringList n | DeviceList n ->
10635 next (); pr "string[] %s" n
10637 next (); pr "bool %s" n
10639 next (); pr "int %s" n
10641 next (); pr "long %s" n
10645 and generate_call () =
10646 pr "guestfs_%s (_handle" name;
10647 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10651 pr " [DllImport (\"%s\")]\n" library;
10652 generate_extern_prototype ();
10654 pr " /// <summary>\n";
10655 pr " /// %s\n" shortdesc;
10656 pr " /// </summary>\n";
10657 generate_public_prototype ();
10659 pr " %s r;\n" (c_return_type ());
10662 pr " if (r %s)\n" (c_error_comparison ());
10663 pr " throw new Error (guestfs_last_error (_handle));\n";
10664 (match fst style with
10667 pr " return r != 0 ? true : false;\n"
10669 pr " Hashtable rr = new Hashtable ();\n";
10670 pr " for (int i = 0; i < r.Length; i += 2)\n";
10671 pr " rr.Add (r[i], r[i+1]);\n";
10673 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10674 | RString _ | RBufferOut _ | RStruct _ | RStringList _
10680 ) all_functions_sorted;
10686 and generate_bindtests () =
10687 generate_header CStyle LGPLv2plus;
10691 #include <stdlib.h>
10692 #include <inttypes.h>
10693 #include <string.h>
10695 #include \"guestfs.h\"
10696 #include \"guestfs-internal.h\"
10697 #include \"guestfs-internal-actions.h\"
10698 #include \"guestfs_protocol.h\"
10700 #define error guestfs_error
10701 #define safe_calloc guestfs_safe_calloc
10702 #define safe_malloc guestfs_safe_malloc
10705 print_strings (char *const *argv)
10710 for (argc = 0; argv[argc] != NULL; ++argc) {
10711 if (argc > 0) printf (\", \");
10712 printf (\"\\\"%%s\\\"\", argv[argc]);
10717 /* The test0 function prints its parameters to stdout. */
10721 match test_functions with
10722 | [] -> assert false
10723 | test0 :: tests -> test0, tests in
10726 let (name, style, _, _, _, _, _) = test0 in
10727 generate_prototype ~extern:false ~semicolon:false ~newline:true
10728 ~handle:"g" ~prefix:"guestfs__" name style;
10733 | Device n | Dev_or_Path n
10736 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
10737 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10738 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
10739 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10740 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
10741 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10743 pr " /* Java changes stdout line buffering so we need this: */\n";
10744 pr " fflush (stdout);\n";
10750 fun (name, style, _, _, _, _, _) ->
10751 if String.sub name (String.length name - 3) 3 <> "err" then (
10752 pr "/* Test normal return. */\n";
10753 generate_prototype ~extern:false ~semicolon:false ~newline:true
10754 ~handle:"g" ~prefix:"guestfs__" name style;
10756 (match fst style with
10761 pr " sscanf (val, \"%%d\", &r);\n";
10764 pr " int64_t r;\n";
10765 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
10768 pr " return STREQ (val, \"true\");\n"
10770 | RConstOptString _ ->
10771 (* Can't return the input string here. Return a static
10772 * string so we ensure we get a segfault if the caller
10773 * tries to free it.
10775 pr " return \"static string\";\n"
10777 pr " return strdup (val);\n"
10779 pr " char **strs;\n";
10781 pr " sscanf (val, \"%%d\", &n);\n";
10782 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10783 pr " for (i = 0; i < n; ++i) {\n";
10784 pr " strs[i] = safe_malloc (g, 16);\n";
10785 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
10787 pr " strs[n] = NULL;\n";
10788 pr " return strs;\n"
10789 | RStruct (_, typ) ->
10790 pr " struct guestfs_%s *r;\n" typ;
10791 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10793 | RStructList (_, typ) ->
10794 pr " struct guestfs_%s_list *r;\n" typ;
10795 pr " r = safe_calloc (g, sizeof *r, 1);\n";
10796 pr " sscanf (val, \"%%d\", &r->len);\n";
10797 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10800 pr " char **strs;\n";
10802 pr " sscanf (val, \"%%d\", &n);\n";
10803 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10804 pr " for (i = 0; i < n; ++i) {\n";
10805 pr " strs[i*2] = safe_malloc (g, 16);\n";
10806 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
10807 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
10808 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10810 pr " strs[n*2] = NULL;\n";
10811 pr " return strs;\n"
10813 pr " return strdup (val);\n"
10818 pr "/* Test error return. */\n";
10819 generate_prototype ~extern:false ~semicolon:false ~newline:true
10820 ~handle:"g" ~prefix:"guestfs__" name style;
10822 pr " error (g, \"error\");\n";
10823 (match fst style with
10824 | RErr | RInt _ | RInt64 _ | RBool _ ->
10826 | RConstString _ | RConstOptString _
10827 | RString _ | RStringList _ | RStruct _
10831 pr " return NULL;\n"
10838 and generate_ocaml_bindtests () =
10839 generate_header OCamlStyle GPLv2plus;
10843 let g = Guestfs.create () in
10847 String.concat " " (
10850 | CallString s -> "\"" ^ s ^ "\""
10851 | CallOptString None -> "None"
10852 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10853 | CallStringList xs ->
10854 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10855 | CallInt i when i >= 0 -> string_of_int i
10856 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10857 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10858 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10859 | CallBool b -> string_of_bool b
10864 generate_lang_bindtests (
10865 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
10868 pr "print_endline \"EOF\"\n"
10870 and generate_perl_bindtests () =
10871 pr "#!/usr/bin/perl -w\n";
10872 generate_header HashStyle GPLv2plus;
10879 my $g = Sys::Guestfs->new ();
10883 String.concat ", " (
10886 | CallString s -> "\"" ^ s ^ "\""
10887 | CallOptString None -> "undef"
10888 | CallOptString (Some s) -> sprintf "\"%s\"" s
10889 | CallStringList xs ->
10890 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10891 | CallInt i -> string_of_int i
10892 | CallInt64 i -> Int64.to_string i
10893 | CallBool b -> if b then "1" else "0"
10898 generate_lang_bindtests (
10899 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10902 pr "print \"EOF\\n\"\n"
10904 and generate_python_bindtests () =
10905 generate_header HashStyle GPLv2plus;
10910 g = guestfs.GuestFS ()
10914 String.concat ", " (
10917 | CallString s -> "\"" ^ s ^ "\""
10918 | CallOptString None -> "None"
10919 | CallOptString (Some s) -> sprintf "\"%s\"" s
10920 | CallStringList xs ->
10921 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10922 | CallInt i -> string_of_int i
10923 | CallInt64 i -> Int64.to_string i
10924 | CallBool b -> if b then "1" else "0"
10929 generate_lang_bindtests (
10930 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10933 pr "print \"EOF\"\n"
10935 and generate_ruby_bindtests () =
10936 generate_header HashStyle GPLv2plus;
10941 g = Guestfs::create()
10945 String.concat ", " (
10948 | CallString s -> "\"" ^ s ^ "\""
10949 | CallOptString None -> "nil"
10950 | CallOptString (Some s) -> sprintf "\"%s\"" s
10951 | CallStringList xs ->
10952 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10953 | CallInt i -> string_of_int i
10954 | CallInt64 i -> Int64.to_string i
10955 | CallBool b -> string_of_bool b
10960 generate_lang_bindtests (
10961 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10964 pr "print \"EOF\\n\"\n"
10966 and generate_java_bindtests () =
10967 generate_header CStyle GPLv2plus;
10970 import com.redhat.et.libguestfs.*;
10972 public class Bindtests {
10973 public static void main (String[] argv)
10976 GuestFS g = new GuestFS ();
10980 String.concat ", " (
10983 | CallString s -> "\"" ^ s ^ "\""
10984 | CallOptString None -> "null"
10985 | CallOptString (Some s) -> sprintf "\"%s\"" s
10986 | CallStringList xs ->
10988 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10989 | CallInt i -> string_of_int i
10990 | CallInt64 i -> Int64.to_string i
10991 | CallBool b -> string_of_bool b
10996 generate_lang_bindtests (
10997 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11001 System.out.println (\"EOF\");
11003 catch (Exception exn) {
11004 System.err.println (exn);
11011 and generate_haskell_bindtests () =
11012 generate_header HaskellStyle GPLv2plus;
11015 module Bindtests where
11016 import qualified Guestfs
11019 g <- Guestfs.create
11023 String.concat " " (
11026 | CallString s -> "\"" ^ s ^ "\""
11027 | CallOptString None -> "Nothing"
11028 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11029 | CallStringList xs ->
11030 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11031 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11032 | CallInt i -> string_of_int i
11033 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11034 | CallInt64 i -> Int64.to_string i
11035 | CallBool true -> "True"
11036 | CallBool false -> "False"
11041 generate_lang_bindtests (
11042 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11045 pr " putStrLn \"EOF\"\n"
11047 (* Language-independent bindings tests - we do it this way to
11048 * ensure there is parity in testing bindings across all languages.
11050 and generate_lang_bindtests call =
11051 call "test0" [CallString "abc"; CallOptString (Some "def");
11052 CallStringList []; CallBool false;
11053 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11054 call "test0" [CallString "abc"; CallOptString None;
11055 CallStringList []; CallBool false;
11056 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11057 call "test0" [CallString ""; CallOptString (Some "def");
11058 CallStringList []; CallBool false;
11059 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11060 call "test0" [CallString ""; CallOptString (Some "");
11061 CallStringList []; CallBool false;
11062 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11063 call "test0" [CallString "abc"; CallOptString (Some "def");
11064 CallStringList ["1"]; CallBool false;
11065 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11066 call "test0" [CallString "abc"; CallOptString (Some "def");
11067 CallStringList ["1"; "2"]; CallBool false;
11068 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11069 call "test0" [CallString "abc"; CallOptString (Some "def");
11070 CallStringList ["1"]; CallBool true;
11071 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11072 call "test0" [CallString "abc"; CallOptString (Some "def");
11073 CallStringList ["1"]; CallBool false;
11074 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11075 call "test0" [CallString "abc"; CallOptString (Some "def");
11076 CallStringList ["1"]; CallBool false;
11077 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11078 call "test0" [CallString "abc"; CallOptString (Some "def");
11079 CallStringList ["1"]; CallBool false;
11080 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11081 call "test0" [CallString "abc"; CallOptString (Some "def");
11082 CallStringList ["1"]; CallBool false;
11083 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11084 call "test0" [CallString "abc"; CallOptString (Some "def");
11085 CallStringList ["1"]; CallBool false;
11086 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11087 call "test0" [CallString "abc"; CallOptString (Some "def");
11088 CallStringList ["1"]; CallBool false;
11089 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11091 (* XXX Add here tests of the return and error functions. *)
11093 (* Code to generator bindings for virt-inspector. Currently only
11094 * implemented for OCaml code (for virt-p2v 2.0).
11096 let rng_input = "inspector/virt-inspector.rng"
11098 (* Read the input file and parse it into internal structures. This is
11099 * by no means a complete RELAX NG parser, but is just enough to be
11100 * able to parse the specific input file.
11103 | Element of string * rng list (* <element name=name/> *)
11104 | Attribute of string * rng list (* <attribute name=name/> *)
11105 | Interleave of rng list (* <interleave/> *)
11106 | ZeroOrMore of rng (* <zeroOrMore/> *)
11107 | OneOrMore of rng (* <oneOrMore/> *)
11108 | Optional of rng (* <optional/> *)
11109 | Choice of string list (* <choice><value/>*</choice> *)
11110 | Value of string (* <value>str</value> *)
11111 | Text (* <text/> *)
11113 let rec string_of_rng = function
11114 | Element (name, xs) ->
11115 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11116 | Attribute (name, xs) ->
11117 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11118 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11119 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11120 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11121 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11122 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11123 | Value value -> "Value \"" ^ value ^ "\""
11126 and string_of_rng_list xs =
11127 String.concat ", " (List.map string_of_rng xs)
11129 let rec parse_rng ?defines context = function
11131 | Xml.Element ("element", ["name", name], children) :: rest ->
11132 Element (name, parse_rng ?defines context children)
11133 :: parse_rng ?defines context rest
11134 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11135 Attribute (name, parse_rng ?defines context children)
11136 :: parse_rng ?defines context rest
11137 | Xml.Element ("interleave", [], children) :: rest ->
11138 Interleave (parse_rng ?defines context children)
11139 :: parse_rng ?defines context rest
11140 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11141 let rng = parse_rng ?defines context [child] in
11143 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11145 failwithf "%s: <zeroOrMore> contains more than one child element"
11148 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11149 let rng = parse_rng ?defines context [child] in
11151 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11153 failwithf "%s: <oneOrMore> contains more than one child element"
11156 | Xml.Element ("optional", [], [child]) :: rest ->
11157 let rng = parse_rng ?defines context [child] in
11159 | [child] -> Optional child :: parse_rng ?defines context rest
11161 failwithf "%s: <optional> contains more than one child element"
11164 | Xml.Element ("choice", [], children) :: rest ->
11165 let values = List.map (
11166 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11168 failwithf "%s: can't handle anything except <value> in <choice>"
11172 :: parse_rng ?defines context rest
11173 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11174 Value value :: parse_rng ?defines context rest
11175 | Xml.Element ("text", [], []) :: rest ->
11176 Text :: parse_rng ?defines context rest
11177 | Xml.Element ("ref", ["name", name], []) :: rest ->
11178 (* Look up the reference. Because of limitations in this parser,
11179 * we can't handle arbitrarily nested <ref> yet. You can only
11180 * use <ref> from inside <start>.
11182 (match defines with
11184 failwithf "%s: contains <ref>, but no refs are defined yet" context
11186 let rng = StringMap.find name map in
11187 rng @ parse_rng ?defines context rest
11190 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11193 let xml = Xml.parse_file rng_input in
11195 | Xml.Element ("grammar", _,
11196 Xml.Element ("start", _, gram) :: defines) ->
11197 (* The <define/> elements are referenced in the <start> section,
11198 * so build a map of those first.
11200 let defines = List.fold_left (
11202 function Xml.Element ("define", ["name", name], defn) ->
11203 StringMap.add name defn map
11205 failwithf "%s: expected <define name=name/>" rng_input
11206 ) StringMap.empty defines in
11207 let defines = StringMap.mapi parse_rng defines in
11209 (* Parse the <start> clause, passing the defines. *)
11210 parse_rng ~defines "<start>" gram
11212 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11215 let name_of_field = function
11216 | Element (name, _) | Attribute (name, _)
11217 | ZeroOrMore (Element (name, _))
11218 | OneOrMore (Element (name, _))
11219 | Optional (Element (name, _)) -> name
11220 | Optional (Attribute (name, _)) -> name
11221 | Text -> (* an unnamed field in an element *)
11224 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11226 (* At the moment this function only generates OCaml types. However we
11227 * should parameterize it later so it can generate types/structs in a
11228 * variety of languages.
11230 let generate_types xs =
11231 (* A simple type is one that can be printed out directly, eg.
11232 * "string option". A complex type is one which has a name and has
11233 * to be defined via another toplevel definition, eg. a struct.
11235 * generate_type generates code for either simple or complex types.
11236 * In the simple case, it returns the string ("string option"). In
11237 * the complex case, it returns the name ("mountpoint"). In the
11238 * complex case it has to print out the definition before returning,
11239 * so it should only be called when we are at the beginning of a
11240 * new line (BOL context).
11242 let rec generate_type = function
11243 | Text -> (* string *)
11245 | Choice values -> (* [`val1|`val2|...] *)
11246 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11247 | ZeroOrMore rng -> (* <rng> list *)
11248 let t, is_simple = generate_type rng in
11249 t ^ " list (* 0 or more *)", is_simple
11250 | OneOrMore rng -> (* <rng> list *)
11251 let t, is_simple = generate_type rng in
11252 t ^ " list (* 1 or more *)", is_simple
11253 (* virt-inspector hack: bool *)
11254 | Optional (Attribute (name, [Value "1"])) ->
11256 | Optional rng -> (* <rng> list *)
11257 let t, is_simple = generate_type rng in
11258 t ^ " option", is_simple
11259 (* type name = { fields ... } *)
11260 | Element (name, fields) when is_attrs_interleave fields ->
11261 generate_type_struct name (get_attrs_interleave fields)
11262 | Element (name, [field]) (* type name = field *)
11263 | Attribute (name, [field]) ->
11264 let t, is_simple = generate_type field in
11265 if is_simple then (t, true)
11267 pr "type %s = %s\n" name t;
11270 | Element (name, fields) -> (* type name = { fields ... } *)
11271 generate_type_struct name fields
11273 failwithf "generate_type failed at: %s" (string_of_rng rng)
11275 and is_attrs_interleave = function
11276 | [Interleave _] -> true
11277 | Attribute _ :: fields -> is_attrs_interleave fields
11278 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11281 and get_attrs_interleave = function
11282 | [Interleave fields] -> fields
11283 | ((Attribute _) as field) :: fields
11284 | ((Optional (Attribute _)) as field) :: fields ->
11285 field :: get_attrs_interleave fields
11286 | _ -> assert false
11288 and generate_types xs =
11289 List.iter (fun x -> ignore (generate_type x)) xs
11291 and generate_type_struct name fields =
11292 (* Calculate the types of the fields first. We have to do this
11293 * before printing anything so we are still in BOL context.
11295 let types = List.map fst (List.map generate_type fields) in
11297 (* Special case of a struct containing just a string and another
11298 * field. Turn it into an assoc list.
11301 | ["string"; other] ->
11302 let fname1, fname2 =
11304 | [f1; f2] -> name_of_field f1, name_of_field f2
11305 | _ -> assert false in
11306 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11310 pr "type %s = {\n" name;
11312 fun (field, ftype) ->
11313 let fname = name_of_field field in
11314 pr " %s_%s : %s;\n" name fname ftype
11315 ) (List.combine fields types);
11317 (* Return the name of this type, and
11318 * false because it's not a simple type.
11325 let generate_parsers xs =
11326 (* As for generate_type above, generate_parser makes a parser for
11327 * some type, and returns the name of the parser it has generated.
11328 * Because it (may) need to print something, it should always be
11329 * called in BOL context.
11331 let rec generate_parser = function
11332 | Text -> (* string *)
11333 "string_child_or_empty"
11334 | Choice values -> (* [`val1|`val2|...] *)
11335 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11337 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11338 | ZeroOrMore rng -> (* <rng> list *)
11339 let pa = generate_parser rng in
11340 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11341 | OneOrMore rng -> (* <rng> list *)
11342 let pa = generate_parser rng in
11343 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11344 (* virt-inspector hack: bool *)
11345 | Optional (Attribute (name, [Value "1"])) ->
11346 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11347 | Optional rng -> (* <rng> list *)
11348 let pa = generate_parser rng in
11349 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11350 (* type name = { fields ... } *)
11351 | Element (name, fields) when is_attrs_interleave fields ->
11352 generate_parser_struct name (get_attrs_interleave fields)
11353 | Element (name, [field]) -> (* type name = field *)
11354 let pa = generate_parser field in
11355 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11356 pr "let %s =\n" parser_name;
11358 pr "let parse_%s = %s\n" name parser_name;
11360 | Attribute (name, [field]) ->
11361 let pa = generate_parser field in
11362 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11363 pr "let %s =\n" parser_name;
11365 pr "let parse_%s = %s\n" name parser_name;
11367 | Element (name, fields) -> (* type name = { fields ... } *)
11368 generate_parser_struct name ([], fields)
11370 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11372 and is_attrs_interleave = function
11373 | [Interleave _] -> true
11374 | Attribute _ :: fields -> is_attrs_interleave fields
11375 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11378 and get_attrs_interleave = function
11379 | [Interleave fields] -> [], fields
11380 | ((Attribute _) as field) :: fields
11381 | ((Optional (Attribute _)) as field) :: fields ->
11382 let attrs, interleaves = get_attrs_interleave fields in
11383 (field :: attrs), interleaves
11384 | _ -> assert false
11386 and generate_parsers xs =
11387 List.iter (fun x -> ignore (generate_parser x)) xs
11389 and generate_parser_struct name (attrs, interleaves) =
11390 (* Generate parsers for the fields first. We have to do this
11391 * before printing anything so we are still in BOL context.
11393 let fields = attrs @ interleaves in
11394 let pas = List.map generate_parser fields in
11396 (* Generate an intermediate tuple from all the fields first.
11397 * If the type is just a string + another field, then we will
11398 * return this directly, otherwise it is turned into a record.
11400 * RELAX NG note: This code treats <interleave> and plain lists of
11401 * fields the same. In other words, it doesn't bother enforcing
11402 * any ordering of fields in the XML.
11404 pr "let parse_%s x =\n" name;
11405 pr " let t = (\n ";
11406 let comma = ref false in
11409 if !comma then pr ",\n ";
11412 | Optional (Attribute (fname, [field])), pa ->
11414 | Optional (Element (fname, [field])), pa ->
11415 pr "%s (optional_child %S x)" pa fname
11416 | Attribute (fname, [Text]), _ ->
11417 pr "attribute %S x" fname
11418 | (ZeroOrMore _ | OneOrMore _), pa ->
11423 let fname = name_of_field field in
11424 pr "%s (child %S x)" pa fname
11425 ) (List.combine fields pas);
11429 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11433 pr " (Obj.magic t : %s)\n" name
11437 | (Optional (Attribute (fname, [field])), pa) ->
11438 pr " %s_%s =\n" name fname;
11440 | (Optional (Element (fname, [field])), pa) ->
11441 pr " %s_%s =\n" name fname;
11442 pr " (let x = optional_child %S x in\n" fname;
11445 let fname = name_of_field field in
11446 pr " %s_%s =\n" name fname;
11447 pr " (let x = child %S x in\n" fname;
11449 ) (List.combine fields pas);
11453 sprintf "parse_%s" name
11456 generate_parsers xs
11458 (* Generate ocaml/guestfs_inspector.mli. *)
11459 let generate_ocaml_inspector_mli () =
11460 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11463 (** This is an OCaml language binding to the external [virt-inspector]
11466 For more information, please read the man page [virt-inspector(1)].
11471 generate_types grammar;
11472 pr "(** The nested information returned from the {!inspect} function. *)\n";
11476 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11477 (** To inspect a libvirt domain called [name], pass a singleton
11478 list: [inspect [name]]. When using libvirt only, you may
11479 optionally pass a libvirt URI using [inspect ~connect:uri ...].
11481 To inspect a disk image or images, pass a list of the filenames
11482 of the disk images: [inspect filenames]
11484 This function inspects the given guest or disk images and
11485 returns a list of operating system(s) found and a large amount
11486 of information about them. In the vast majority of cases,
11487 a virtual machine only contains a single operating system.
11489 If the optional [~xml] parameter is given, then this function
11490 skips running the external virt-inspector program and just
11491 parses the given XML directly (which is expected to be XML
11492 produced from a previous run of virt-inspector). The list of
11493 names and connect URI are ignored in this case.
11495 This function can throw a wide variety of exceptions, for example
11496 if the external virt-inspector program cannot be found, or if
11497 it doesn't generate valid XML.
11501 (* Generate ocaml/guestfs_inspector.ml. *)
11502 let generate_ocaml_inspector_ml () =
11503 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11508 generate_types grammar;
11512 (* Misc functions which are used by the parser code below. *)
11513 let first_child = function
11514 | Xml.Element (_, _, c::_) -> c
11515 | Xml.Element (name, _, []) ->
11516 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11517 | Xml.PCData str ->
11518 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11520 let string_child_or_empty = function
11521 | Xml.Element (_, _, [Xml.PCData s]) -> s
11522 | Xml.Element (_, _, []) -> \"\"
11523 | Xml.Element (x, _, _) ->
11524 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11526 | Xml.PCData str ->
11527 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11529 let optional_child name xml =
11530 let children = Xml.children xml in
11532 Some (List.find (function
11533 | Xml.Element (n, _, _) when n = name -> true
11534 | _ -> false) children)
11538 let child name xml =
11539 match optional_child name xml with
11542 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11544 let attribute name xml =
11545 try Xml.attrib xml name
11546 with Xml.No_attribute _ ->
11547 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11551 generate_parsers grammar;
11555 (* Run external virt-inspector, then use parser to parse the XML. *)
11556 let inspect ?connect ?xml names =
11560 if names = [] then invalid_arg \"inspect: no names given\";
11561 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11562 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11564 let cmd = List.map Filename.quote cmd in
11565 let cmd = String.concat \" \" cmd in
11566 let chan = open_process_in cmd in
11567 let xml = Xml.parse_in chan in
11568 (match close_process_in chan with
11570 | WEXITED _ -> failwith \"external virt-inspector command failed\"
11571 | WSIGNALED i | WSTOPPED i ->
11572 failwith (\"external virt-inspector command died or stopped on sig \" ^
11577 Xml.parse_string doc in
11578 parse_operatingsystems xml
11581 (* This is used to generate the src/MAX_PROC_NR file which
11582 * contains the maximum procedure number, a surrogate for the
11583 * ABI version number. See src/Makefile.am for the details.
11585 and generate_max_proc_nr () =
11586 let proc_nrs = List.map (
11587 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11588 ) daemon_functions in
11590 let max_proc_nr = List.fold_left max 0 proc_nrs in
11592 pr "%d\n" max_proc_nr
11594 let output_to filename k =
11595 let filename_new = filename ^ ".new" in
11596 chan := open_out filename_new;
11599 chan := Pervasives.stdout;
11601 (* Is the new file different from the current file? *)
11602 if Sys.file_exists filename && files_equal filename filename_new then
11603 unlink filename_new (* same, so skip it *)
11605 (* different, overwrite old one *)
11606 (try chmod filename 0o644 with Unix_error _ -> ());
11607 rename filename_new filename;
11608 chmod filename 0o444;
11609 printf "written %s\n%!" filename;
11612 let perror msg = function
11613 | Unix_error (err, _, _) ->
11614 eprintf "%s: %s\n" msg (error_message err)
11616 eprintf "%s: %s\n" msg (Printexc.to_string exn)
11618 (* Main program. *)
11621 try openfile "HACKING" [O_RDWR] 0
11623 | Unix_error (ENOENT, _, _) ->
11625 You are probably running this from the wrong directory.
11626 Run it from the top source directory using the command
11631 perror "open: HACKING" exn;
11634 (* Acquire a lock so parallel builds won't try to run the generator
11635 * twice at the same time. Subsequent builds will wait for the first
11636 * one to finish. Note the lock is released implicitly when the
11639 (try lockf lock_fd F_LOCK 1
11641 perror "lock: HACKING" exn;
11644 check_functions ();
11646 output_to "src/guestfs_protocol.x" generate_xdr;
11647 output_to "src/guestfs-structs.h" generate_structs_h;
11648 output_to "src/guestfs-actions.h" generate_actions_h;
11649 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11650 output_to "src/guestfs-actions.c" generate_client_actions;
11651 output_to "src/guestfs-bindtests.c" generate_bindtests;
11652 output_to "src/guestfs-structs.pod" generate_structs_pod;
11653 output_to "src/guestfs-actions.pod" generate_actions_pod;
11654 output_to "src/guestfs-availability.pod" generate_availability_pod;
11655 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11656 output_to "src/libguestfs.syms" generate_linker_script;
11657 output_to "daemon/actions.h" generate_daemon_actions_h;
11658 output_to "daemon/stubs.c" generate_daemon_actions;
11659 output_to "daemon/names.c" generate_daemon_names;
11660 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11661 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11662 output_to "capitests/tests.c" generate_tests;
11663 output_to "fish/cmds.c" generate_fish_cmds;
11664 output_to "fish/completion.c" generate_fish_completion;
11665 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11666 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11667 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11668 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11669 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11670 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11671 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11672 output_to "perl/Guestfs.xs" generate_perl_xs;
11673 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11674 output_to "perl/bindtests.pl" generate_perl_bindtests;
11675 output_to "python/guestfs-py.c" generate_python_c;
11676 output_to "python/guestfs.py" generate_python_py;
11677 output_to "python/bindtests.py" generate_python_bindtests;
11678 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11679 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11680 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11684 let cols = cols_of_struct typ in
11685 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11686 output_to filename (generate_java_struct jtyp cols);
11689 output_to "java/Makefile.inc" generate_java_makefile_inc;
11690 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11691 output_to "java/Bindtests.java" generate_java_bindtests;
11692 output_to "haskell/Guestfs.hs" generate_haskell_hs;
11693 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11694 output_to "csharp/Libguestfs.cs" generate_csharp;
11696 (* Always generate this file last, and unconditionally. It's used
11697 * by the Makefile to know when we must re-run the generator.
11699 let chan = open_out "src/stamp-generator" in
11700 fprintf chan "1\n";
11703 printf "generated %d lines of code\n" !lines