3 * Copyright (C) 2009-2010 Red Hat Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 (* This script generates a large amount of code and documentation for
21 * all the daemon actions.
23 * To add a new action there are only two files you need to change,
24 * this one to describe the interface (see the big table of
25 * 'daemon_functions' below), and daemon/<somefile>.c to write the
28 * After editing this file, run it (./src/generator.ml) to regenerate
29 * all the output files. 'make' will rerun this automatically when
30 * necessary. Note that if you are using a separate build directory
31 * you must run generator.ml from the _source_ directory.
33 * IMPORTANT: This script should NOT print any warnings. If it prints
34 * warnings, you should treat them as errors.
37 * (1) In emacs, install tuareg-mode to display and format OCaml code
38 * correctly. 'vim' comes with a good OCaml editing mode by default.
39 * (2) Read the resources at http://ocaml-tutorial.org/
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
51 type style = ret * args
53 (* "RErr" as a return value means an int used as a simple error
54 * indication, ie. 0 or -1.
58 (* "RInt" as a return value means an int which is -1 for error
59 * or any value >= 0 on success. Only use this for smallish
60 * positive ints (0 <= i < 2^30).
64 (* "RInt64" is the same as RInt, but is guaranteed to be able
65 * to return a full 64 bit value, _except_ that -1 means error
66 * (so -1 cannot be a valid, non-error return value).
70 (* "RBool" is a bool return value which can be true/false or
75 (* "RConstString" is a string that refers to a constant value.
76 * The return value must NOT be NULL (since NULL indicates
79 * Try to avoid using this. In particular you cannot use this
80 * for values returned from the daemon, because there is no
81 * thread-safe way to return them in the C API.
83 | RConstString of string
85 (* "RConstOptString" is an even more broken version of
86 * "RConstString". The returned string may be NULL and there
87 * is no way to return an error indication. Avoid using this!
89 | RConstOptString of string
91 (* "RString" is a returned string. It must NOT be NULL, since
92 * a NULL return indicates an error. The caller frees this.
96 (* "RStringList" is a list of strings. No string in the list
97 * can be NULL. The caller frees the strings and the array.
99 | RStringList of string
101 (* "RStruct" is a function which returns a single named structure
102 * or an error indication (in C, a struct, and in other languages
103 * with varying representations, but usually very efficient). See
104 * after the function list below for the structures.
106 | RStruct of string * string (* name of retval, name of struct *)
108 (* "RStructList" is a function which returns either a list/array
109 * of structures (could be zero-length), or an error indication.
111 | RStructList of string * string (* name of retval, name of struct *)
113 (* Key-value pairs of untyped strings. Turns into a hashtable or
114 * dictionary in languages which support it. DON'T use this as a
115 * general "bucket" for results. Prefer a stronger typed return
116 * value if one is available, or write a custom struct. Don't use
117 * this if the list could potentially be very long, since it is
118 * inefficient. Keys should be unique. NULLs are not permitted.
120 | RHashtable of string
122 (* "RBufferOut" is handled almost exactly like RString, but
123 * it allows the string to contain arbitrary 8 bit data including
124 * ASCII NUL. In the C API this causes an implicit extra parameter
125 * to be added of type <size_t *size_r>. The extra parameter
126 * returns the actual size of the return buffer in bytes.
128 * Other programming languages support strings with arbitrary 8 bit
131 * At the RPC layer we have to use the opaque<> type instead of
132 * string<>. Returned data is still limited to the max message
135 | RBufferOut of string
137 and args = argt list (* Function parameters, guestfs handle is implicit. *)
139 (* Note in future we should allow a "variable args" parameter as
140 * the final parameter, to allow commands like
141 * chmod mode file [file(s)...]
142 * This is not implemented yet, but many commands (such as chmod)
143 * are currently defined with the argument order keeping this future
144 * possibility in mind.
147 | String of string (* const char *name, cannot be NULL *)
148 | Device of string (* /dev device name, cannot be NULL *)
149 | Pathname of string (* file name, cannot be NULL *)
150 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151 | OptString of string (* const char *name, may be NULL *)
152 | StringList of string(* list of strings (each string cannot be NULL) *)
153 | DeviceList of string(* list of Device names (each cannot be NULL) *)
154 | Bool of string (* boolean *)
155 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
156 | Int64 of string (* any 64 bit int *)
157 (* These are treated as filenames (simple string parameters) in
158 * the C API and bindings. But in the RPC protocol, we transfer
159 * the actual file content up to or down from the daemon.
160 * FileIn: local machine -> daemon (in request)
161 * FileOut: daemon -> local machine (in reply)
162 * In guestfish (only), the special name "-" means read from
163 * stdin or write to stdout.
167 (* Opaque buffer which can contain arbitrary 8 bit data.
168 * In the C API, this is expressed as <const char *, size_t> pair.
169 * Most other languages have a string type which can contain
170 * ASCII NUL. We use whatever type is appropriate for each
172 * Buffers are limited by the total message size. To transfer
173 * large blocks of data, use FileIn/FileOut parameters instead.
174 * To return an arbitrary buffer, use RBufferOut.
179 | ProtocolLimitWarning (* display warning about protocol size limits *)
180 | DangerWillRobinson (* flags particularly dangerous commands *)
181 | FishAlias of string (* provide an alias for this cmd in guestfish *)
182 | FishOutput of fish_output_t (* how to display output in guestfish *)
183 | NotInFish (* do not export via guestfish *)
184 | NotInDocs (* do not add this function to documentation *)
185 | DeprecatedBy of string (* function is deprecated, use .. instead *)
186 | Optional of string (* function is part of an optional group *)
189 | FishOutputOctal (* for int return, print in octal *)
190 | FishOutputHexadecimal (* for int return, print in hex *)
192 (* You can supply zero or as many tests as you want per API call.
194 * Note that the test environment has 3 block devices, of size 500MB,
195 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196 * a fourth ISO block device with some known files on it (/dev/sdd).
198 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199 * Number of cylinders was 63 for IDE emulated disks with precisely
200 * the same size. How exactly this is calculated is a mystery.
202 * The ISO block device (/dev/sdd) comes from images/test.iso.
204 * To be able to run the tests in a reasonable amount of time,
205 * the virtual machine and block devices are reused between tests.
206 * So don't try testing kill_subprocess :-x
208 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
210 * Don't assume anything about the previous contents of the block
211 * devices. Use 'Init*' to create some initial scenarios.
213 * You can add a prerequisite clause to any individual test. This
214 * is a run-time check, which, if it fails, causes the test to be
215 * skipped. Useful if testing a command which might not work on
216 * all variations of libguestfs builds. A test that has prerequisite
217 * of 'Always' is run unconditionally.
219 * In addition, packagers can skip individual tests by setting the
220 * environment variables: eg:
221 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
222 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
224 type tests = (test_init * test_prereq * test) list
226 (* Run the command sequence and just expect nothing to fail. *)
229 (* Run the command sequence and expect the output of the final
230 * command to be the string.
232 | TestOutput of seq * string
234 (* Run the command sequence and expect the output of the final
235 * command to be the list of strings.
237 | TestOutputList of seq * string list
239 (* Run the command sequence and expect the output of the final
240 * command to be the list of block devices (could be either
241 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242 * character of each string).
244 | TestOutputListOfDevices of seq * string list
246 (* Run the command sequence and expect the output of the final
247 * command to be the integer.
249 | TestOutputInt of seq * int
251 (* Run the command sequence and expect the output of the final
252 * command to be <op> <int>, eg. ">=", "1".
254 | TestOutputIntOp of seq * string * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a true value (!= 0 or != NULL).
259 | TestOutputTrue of seq
261 (* Run the command sequence and expect the output of the final
262 * command to be a false value (== 0 or == NULL, but not an error).
264 | TestOutputFalse of seq
266 (* Run the command sequence and expect the output of the final
267 * command to be a list of the given length (but don't care about
270 | TestOutputLength of seq * int
272 (* Run the command sequence and expect the output of the final
273 * command to be a buffer (RBufferOut), ie. string + size.
275 | TestOutputBuffer of seq * string
277 (* Run the command sequence and expect the output of the final
278 * command to be a structure.
280 | TestOutputStruct of seq * test_field_compare list
282 (* Run the command sequence and expect the final command (only)
285 | TestLastFail of seq
287 and test_field_compare =
288 | CompareWithInt of string * int
289 | CompareWithIntOp of string * string * int
290 | CompareWithString of string * string
291 | CompareFieldsIntEq of string * string
292 | CompareFieldsStrEq of string * string
294 (* Test prerequisites. *)
296 (* Test always runs. *)
299 (* Test is currently disabled - eg. it fails, or it tests some
300 * unimplemented feature.
304 (* 'string' is some C code (a function body) that should return
305 * true or false. The test will run if the code returns true.
309 (* As for 'If' but the test runs _unless_ the code returns true. *)
312 (* Run the test only if 'string' is available in the daemon. *)
313 | IfAvailable of string
315 (* Some initial scenarios for testing. *)
317 (* Do nothing, block devices could contain random stuff including
318 * LVM PVs, and some filesystems might be mounted. This is usually
323 (* Block devices are empty and no filesystems are mounted. *)
326 (* /dev/sda contains a single partition /dev/sda1, with random
327 * content. /dev/sdb and /dev/sdc may have random content.
332 (* /dev/sda contains a single partition /dev/sda1, which is formatted
333 * as ext2, empty [except for lost+found] and mounted on /.
334 * /dev/sdb and /dev/sdc may have random content.
340 * /dev/sda1 (is a PV):
341 * /dev/VG/LV (size 8MB):
342 * formatted as ext2, empty [except for lost+found], mounted on /
343 * /dev/sdb and /dev/sdc may have random content.
347 (* /dev/sdd (the ISO, see images/ directory in source)
352 (* Sequence of commands for testing. *)
354 and cmd = string list
356 (* Note about long descriptions: When referring to another
357 * action, use the format C<guestfs_other> (ie. the full name of
358 * the C function). This will be replaced as appropriate in other
361 * Apart from that, long descriptions are just perldoc paragraphs.
364 (* Generate a 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";
391 let test_all_rets = [
392 (* except for RErr, which is tested thoroughly elsewhere *)
393 "test0rint", RInt "valout";
394 "test0rint64", RInt64 "valout";
395 "test0rbool", RBool "valout";
396 "test0rconststring", RConstString "valout";
397 "test0rconstoptstring", RConstOptString "valout";
398 "test0rstring", RString "valout";
399 "test0rstringlist", RStringList "valout";
400 "test0rstruct", RStruct ("valout", "lvm_pv");
401 "test0rstructlist", RStructList ("valout", "lvm_pv");
402 "test0rhashtable", RHashtable "valout";
405 let test_functions = [
406 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
408 "internal test function - do not use",
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
414 It echos the contents of each parameter to stdout.
416 You probably don't want to call this function.");
420 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
422 "internal test function - do not use",
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
428 It converts string C<val> to the return type.
430 You probably don't want to call this function.");
431 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
433 "internal test function - do not use",
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
439 This function always returns an error.
441 You probably don't want to call this function.")]
445 (* non_daemon_functions are any functions which don't get processed
446 * in the daemon, eg. functions for setting and getting local
447 * configuration values.
450 let non_daemon_functions = test_functions @ [
451 ("launch", (RErr, []), -1, [FishAlias "run"],
453 "launch the qemu subprocess",
455 Internally libguestfs is implemented by running a virtual machine
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
461 ("wait_ready", (RErr, []), -1, [NotInFish],
463 "wait until the qemu subprocess launches (no op)",
465 This function is a no op.
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete. However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
476 ("kill_subprocess", (RErr, []), -1, [],
478 "kill the qemu subprocess",
480 This kills the qemu subprocess. You should never need to call this.");
482 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
484 "add an image to examine or modify",
486 This function adds a virtual machine disk image C<filename> to the
487 guest. The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
491 You don't necessarily need to be root when using libguestfs. However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>. In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
508 Note that this call checks for the existence of C<filename>. This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
511 the general C<guestfs_config> call instead.");
513 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
515 "add a CD-ROM disk image to examine",
517 This function adds a virtual CD-ROM disk image to the guest.
519 This is equivalent to the qemu parameter C<-cdrom filename>.
527 This call checks for the existence of C<filename>. This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
530 the general C<guestfs_config> call instead.
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
540 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
542 "add a drive in snapshot mode (read-only)",
544 This adds a drive in snapshot mode, making it effectively
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed. We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,if=...>.
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>. In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
561 Note that this call checks for the existence of C<filename>. This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
564 the general C<guestfs_config> call instead.");
566 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568 "add qemu parameters",
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>. Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
575 The first character of C<param> string must be a C<-> (dash).
577 C<value> can be NULL.");
579 ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
581 "set the qemu binary",
583 Set the qemu binary that we will use.
585 The default is chosen when the library was compiled by the
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
593 Note that you should call this function as early as possible
594 after creating the handle. This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results. Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
601 ("get_qemu", (RConstString "qemu", []), -1, [],
602 [InitNone, Always, TestRun (
604 "get the qemu binary",
606 Return the current qemu binary.
608 This is always non-NULL. If it wasn't set already, then this will
609 return the default qemu binary name.");
611 ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
613 "set the search path",
615 Set the path that libguestfs searches for kernel and initrd.img.
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
620 Setting C<path> to C<NULL> restores the default path.");
622 ("get_path", (RConstString "path", []), -1, [],
623 [InitNone, Always, TestRun (
625 "get the search path",
627 Return the current search path.
629 This is always non-NULL. If it wasn't set already, then this will
630 return the default path.");
632 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634 "add options to kernel command line",
636 This function is used to add additional options to the
637 guest kernel command line.
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
645 ("get_append", (RConstOptString "append", []), -1, [],
646 (* This cannot be tested with the current framework. The
647 * function can return NULL in normal operations, which the
648 * test framework interprets as an error.
651 "get the additional kernel options",
653 Return the additional kernel options which are added to the
654 guest kernel command line.
656 If C<NULL> then no options are added.");
658 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
662 If C<autosync> is true, this enables autosync. Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
670 ("get_autosync", (RBool "autosync", []), -1, [],
671 [InitNone, Always, TestRun (
672 [["get_autosync"]])],
675 Get the autosync flag.");
677 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686 ("get_verbose", (RBool "verbose", []), -1, [],
690 This returns the verbose messages flag.");
692 ("is_ready", (RBool "ready", []), -1, [],
693 [InitNone, Always, TestOutputTrue (
695 "is ready to accept commands",
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
700 For more information on states, see L<guestfs(3)>.");
702 ("is_config", (RBool "config", []), -1, [],
703 [InitNone, Always, TestOutputFalse (
705 "is in configuration state",
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
710 For more information on states, see L<guestfs(3)>.");
712 ("is_launching", (RBool "launching", []), -1, [],
713 [InitNone, Always, TestOutputFalse (
714 [["is_launching"]])],
715 "is launching subprocess",
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
720 For more information on states, see L<guestfs(3)>.");
722 ("is_busy", (RBool "busy", []), -1, [],
723 [InitNone, Always, TestOutputFalse (
725 "is busy processing a command",
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
730 For more information on states, see L<guestfs(3)>.");
732 ("get_state", (RInt "state", []), -1, [],
734 "get the current state",
736 This returns the current state as an opaque integer. This is
737 only useful for printing debug and internal error messages.
739 For more information on states, see L<guestfs(3)>.");
741 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742 [InitNone, Always, TestOutputInt (
743 [["set_memsize"; "500"];
744 ["get_memsize"]], 500)],
745 "set memory allocated to the qemu subprocess",
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess. This only has any effect if called before
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
758 ("get_memsize", (RInt "memsize", []), -1, [],
759 [InitNone, Always, TestOutputIntOp (
760 [["get_memsize"]], ">=", 256)],
761 "get memory allocated to the qemu subprocess",
763 This gets the memory size in megabytes allocated to the
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
773 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774 [InitNone, Always, TestOutputIntOp (
775 [["get_pid"]], ">=", 1)],
776 "get PID of qemu subprocess",
778 Return the process ID of the qemu subprocess. If there is no
779 qemu subprocess, then this will return an error.
781 This is an internal call used for debugging and testing.");
783 ("version", (RStruct ("version", "version"), []), -1, [],
784 [InitNone, Always, TestOutputStruct (
785 [["version"]], [CompareWithInt ("major", 1)])],
786 "get the library version number",
788 Return the libguestfs version number that the program is linked
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against. You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
796 This call was added in version C<1.0.58>. In previous
797 versions of libguestfs there was no way to get the version
798 number. From C code you can use dynamic linker functions
799 to find out if this symbol exists (if it doesn't, then
800 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 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
813 I<Note:> Don't use this call to test for availability
814 of features. In enterprise distributions we backport
815 features from later versions into earlier versions,
816 making this an unreliable way to test for features.
817 Use C<guestfs_available> instead.");
819 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
820 [InitNone, Always, TestOutputTrue (
821 [["set_selinux"; "true"];
823 "set SELinux enabled or disabled at appliance boot",
825 This sets the selinux flag that is passed to the appliance
826 at boot time. The default is C<selinux=0> (disabled).
828 Note that if SELinux is enabled, it is always in
829 Permissive mode (C<enforcing=0>).
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
834 ("get_selinux", (RBool "selinux", []), -1, [],
836 "get SELinux enabled flag",
838 This returns the current setting of the selinux flag which
839 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
841 For more information on the architecture of libguestfs,
842 see L<guestfs(3)>.");
844 ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
845 [InitNone, Always, TestOutputFalse (
846 [["set_trace"; "false"];
848 "enable or disable command traces",
850 If the command trace flag is set to 1, then commands are
851 printed on stdout before they are executed in a format
852 which is very similar to the one used by guestfish. In
853 other words, you can run a program with this enabled, and
854 you will get out a script which you can feed to guestfish
855 to perform the same set of actions.
857 If you want to trace C API calls into libguestfs (and
858 other libraries) then possibly a better way is to use
859 the external ltrace(1) command.
861 Command traces are disabled unless the environment variable
862 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
864 ("get_trace", (RBool "trace", []), -1, [],
866 "get command trace enabled flag",
868 Return the command trace flag.");
870 ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
871 [InitNone, Always, TestOutputFalse (
872 [["set_direct"; "false"];
874 "enable or disable direct appliance mode",
876 If the direct appliance mode flag is enabled, then stdin and
877 stdout are passed directly through to the appliance once it
880 One consequence of this is that log messages aren't caught
881 by the library and handled by C<guestfs_set_log_message_callback>,
882 but go straight to stdout.
884 You probably don't want to use this unless you know what you
887 The default is disabled.");
889 ("get_direct", (RBool "direct", []), -1, [],
891 "get direct appliance mode flag",
893 Return the direct appliance mode flag.");
895 ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
896 [InitNone, Always, TestOutputTrue (
897 [["set_recovery_proc"; "true"];
898 ["get_recovery_proc"]])],
899 "enable or disable the recovery process",
901 If this is called with the parameter C<false> then
902 C<guestfs_launch> does not create a recovery process. The
903 purpose of the recovery process is to stop runaway qemu
904 processes in the case where the main program aborts abruptly.
906 This only has any effect if called before C<guestfs_launch>,
907 and the default is true.
909 About the only time when you would want to disable this is
910 if the main process will fork itself into the background
911 (\"daemonize\" itself). In this case the recovery process
912 thinks that the main program has disappeared and so kills
913 qemu, which is not very helpful.");
915 ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
917 "get recovery process enabled flag",
919 Return the recovery process enabled flag.");
921 ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923 "add a drive specifying the QEMU block emulation to use",
925 This is the same as C<guestfs_add_drive> but it allows you
926 to specify the QEMU interface emulation to use at run time.");
928 ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
930 "add a drive read-only specifying the QEMU block emulation to use",
932 This is the same as C<guestfs_add_drive_ro> but it allows you
933 to specify the QEMU interface emulation to use at run time.");
937 (* daemon_functions are any functions which cause some action
938 * to take place in the daemon.
941 let daemon_functions = [
942 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
943 [InitEmpty, Always, TestOutput (
944 [["part_disk"; "/dev/sda"; "mbr"];
945 ["mkfs"; "ext2"; "/dev/sda1"];
946 ["mount"; "/dev/sda1"; "/"];
947 ["write"; "/new"; "new file contents"];
948 ["cat"; "/new"]], "new file contents")],
949 "mount a guest disk at a position in the filesystem",
951 Mount a guest disk at a position in the filesystem. Block devices
952 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
953 the guest. If those block devices contain partitions, they will have
954 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
957 The rules are the same as for L<mount(2)>: A filesystem must
958 first be mounted on C</> before others can be mounted. Other
959 filesystems can only be mounted on directories which already
962 The mounted filesystem is writable, if we have sufficient permissions
963 on the underlying device.
966 When you use this call, the filesystem options C<sync> and C<noatime>
967 are set implicitly. This was originally done because we thought it
968 would improve reliability, but it turns out that I<-o sync> has a
969 very large negative performance impact and negligible effect on
970 reliability. Therefore we recommend that you avoid using
971 C<guestfs_mount> in any code that needs performance, and instead
972 use C<guestfs_mount_options> (use an empty string for the first
973 parameter if you don't want any options).");
975 ("sync", (RErr, []), 2, [],
976 [ InitEmpty, Always, TestRun [["sync"]]],
977 "sync disks, writes are flushed through to the disk image",
979 This syncs the disk, so that any writes are flushed through to the
980 underlying disk image.
982 You should always call this if you have modified a disk image, before
983 closing the handle.");
985 ("touch", (RErr, [Pathname "path"]), 3, [],
986 [InitBasicFS, Always, TestOutputTrue (
988 ["exists"; "/new"]])],
989 "update file timestamps or create a new file",
991 Touch acts like the L<touch(1)> command. It can be used to
992 update the timestamps on a file, or, if the file does not exist,
993 to create a new zero-length file.
995 This command only works on regular files, and will fail on other
996 file types such as directories, symbolic links, block special etc.");
998 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
999 [InitISOFS, Always, TestOutput (
1000 [["cat"; "/known-2"]], "abcdef\n")],
1001 "list the contents of a file",
1003 Return the contents of the file named C<path>.
1005 Note that this function cannot correctly handle binary files
1006 (specifically, files containing C<\\0> character which is treated
1007 as end of string). For those you need to use the C<guestfs_read_file>
1008 or C<guestfs_download> functions which have a more complex interface.");
1010 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1011 [], (* XXX Tricky to test because it depends on the exact format
1012 * of the 'ls -l' command, which changes between F10 and F11.
1014 "list the files in a directory (long format)",
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd) in the format of 'ls -la'.
1019 This command is mostly useful for interactive sessions. It
1020 is I<not> intended that you try to parse the output string.");
1022 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1023 [InitBasicFS, Always, TestOutputList (
1025 ["touch"; "/newer"];
1026 ["touch"; "/newest"];
1027 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1028 "list the files in a directory",
1030 List the files in C<directory> (relative to the root directory,
1031 there is no cwd). The '.' and '..' entries are not returned, but
1032 hidden files are shown.
1034 This command is mostly useful for interactive sessions. Programs
1035 should probably use C<guestfs_readdir> instead.");
1037 ("list_devices", (RStringList "devices", []), 7, [],
1038 [InitEmpty, Always, TestOutputListOfDevices (
1039 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1040 "list the block devices",
1042 List all the block devices.
1044 The full block device names are returned, eg. C</dev/sda>");
1046 ("list_partitions", (RStringList "partitions", []), 8, [],
1047 [InitBasicFS, Always, TestOutputListOfDevices (
1048 [["list_partitions"]], ["/dev/sda1"]);
1049 InitEmpty, Always, TestOutputListOfDevices (
1050 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1052 "list the partitions",
1054 List all the partitions detected on all block devices.
1056 The full partition device names are returned, eg. C</dev/sda1>
1058 This does not return logical volumes. For that you will need to
1059 call C<guestfs_lvs>.");
1061 ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1062 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1063 [["pvs"]], ["/dev/sda1"]);
1064 InitEmpty, Always, TestOutputListOfDevices (
1065 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066 ["pvcreate"; "/dev/sda1"];
1067 ["pvcreate"; "/dev/sda2"];
1068 ["pvcreate"; "/dev/sda3"];
1069 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1070 "list the LVM physical volumes (PVs)",
1072 List all the physical volumes detected. This is the equivalent
1073 of the L<pvs(8)> command.
1075 This returns a list of just the device names that contain
1076 PVs (eg. C</dev/sda2>).
1078 See also C<guestfs_pvs_full>.");
1080 ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1081 [InitBasicFSonLVM, Always, TestOutputList (
1083 InitEmpty, Always, TestOutputList (
1084 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1085 ["pvcreate"; "/dev/sda1"];
1086 ["pvcreate"; "/dev/sda2"];
1087 ["pvcreate"; "/dev/sda3"];
1088 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1089 ["vgcreate"; "VG2"; "/dev/sda3"];
1090 ["vgs"]], ["VG1"; "VG2"])],
1091 "list the LVM volume groups (VGs)",
1093 List all the volumes groups detected. This is the equivalent
1094 of the L<vgs(8)> command.
1096 This returns a list of just the volume group names that were
1097 detected (eg. C<VolGroup00>).
1099 See also C<guestfs_vgs_full>.");
1101 ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1102 [InitBasicFSonLVM, Always, TestOutputList (
1103 [["lvs"]], ["/dev/VG/LV"]);
1104 InitEmpty, Always, TestOutputList (
1105 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1106 ["pvcreate"; "/dev/sda1"];
1107 ["pvcreate"; "/dev/sda2"];
1108 ["pvcreate"; "/dev/sda3"];
1109 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1110 ["vgcreate"; "VG2"; "/dev/sda3"];
1111 ["lvcreate"; "LV1"; "VG1"; "50"];
1112 ["lvcreate"; "LV2"; "VG1"; "50"];
1113 ["lvcreate"; "LV3"; "VG2"; "50"];
1114 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1115 "list the LVM logical volumes (LVs)",
1117 List all the logical volumes detected. This is the equivalent
1118 of the L<lvs(8)> command.
1120 This returns a list of the logical volume device names
1121 (eg. C</dev/VolGroup00/LogVol00>).
1123 See also C<guestfs_lvs_full>.");
1125 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1126 [], (* XXX how to test? *)
1127 "list the LVM physical volumes (PVs)",
1129 List all the physical volumes detected. This is the equivalent
1130 of the L<pvs(8)> command. The \"full\" version includes all fields.");
1132 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1133 [], (* XXX how to test? *)
1134 "list the LVM volume groups (VGs)",
1136 List all the volumes groups detected. This is the equivalent
1137 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1139 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1140 [], (* XXX how to test? *)
1141 "list the LVM logical volumes (LVs)",
1143 List all the logical volumes detected. This is the equivalent
1144 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1146 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1147 [InitISOFS, Always, TestOutputList (
1148 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1149 InitISOFS, Always, TestOutputList (
1150 [["read_lines"; "/empty"]], [])],
1151 "read file as lines",
1153 Return the contents of the file named C<path>.
1155 The file contents are returned as a list of lines. Trailing
1156 C<LF> and C<CRLF> character sequences are I<not> returned.
1158 Note that this function cannot correctly handle binary files
1159 (specifically, files containing C<\\0> character which is treated
1160 as end of line). For those you need to use the C<guestfs_read_file>
1161 function which has a more complex interface.");
1163 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1164 [], (* XXX Augeas code needs tests. *)
1165 "create a new Augeas handle",
1167 Create a new Augeas handle for editing configuration files.
1168 If there was any previous Augeas handle associated with this
1169 guestfs session, then it is closed.
1171 You must call this before using any other C<guestfs_aug_*>
1174 C<root> is the filesystem root. C<root> must not be NULL,
1177 The flags are the same as the flags defined in
1178 E<lt>augeas.hE<gt>, the logical I<or> of the following
1183 =item C<AUG_SAVE_BACKUP> = 1
1185 Keep the original file with a C<.augsave> extension.
1187 =item C<AUG_SAVE_NEWFILE> = 2
1189 Save changes into a file with extension C<.augnew>, and
1190 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1192 =item C<AUG_TYPE_CHECK> = 4
1194 Typecheck lenses (can be expensive).
1196 =item C<AUG_NO_STDINC> = 8
1198 Do not use standard load path for modules.
1200 =item C<AUG_SAVE_NOOP> = 16
1202 Make save a no-op, just record what would have been changed.
1204 =item C<AUG_NO_LOAD> = 32
1206 Do not load the tree in C<guestfs_aug_init>.
1210 To close the handle, you can call C<guestfs_aug_close>.
1212 To find out more about Augeas, see L<http://augeas.net/>.");
1214 ("aug_close", (RErr, []), 26, [Optional "augeas"],
1215 [], (* XXX Augeas code needs tests. *)
1216 "close the current Augeas handle",
1218 Close the current Augeas handle and free up any resources
1219 used by it. After calling this, you have to call
1220 C<guestfs_aug_init> again before you can use any other
1221 Augeas functions.");
1223 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1224 [], (* XXX Augeas code needs tests. *)
1225 "define an Augeas variable",
1227 Defines an Augeas variable C<name> whose value is the result
1228 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1231 On success this returns the number of nodes in C<expr>, or
1232 C<0> if C<expr> evaluates to something which is not a nodeset.");
1234 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1235 [], (* XXX Augeas code needs tests. *)
1236 "define an Augeas node",
1238 Defines a variable C<name> whose value is the result of
1241 If C<expr> evaluates to an empty nodeset, a node is created,
1242 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1243 C<name> will be the nodeset containing that single node.
1245 On success this returns a pair containing the
1246 number of nodes in the nodeset, and a boolean flag
1247 if a node was created.");
1249 ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1250 [], (* XXX Augeas code needs tests. *)
1251 "look up the value of an Augeas path",
1253 Look up the value associated with C<path>. If C<path>
1254 matches exactly one node, the C<value> is returned.");
1256 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1257 [], (* XXX Augeas code needs tests. *)
1258 "set Augeas path to value",
1260 Set the value associated with C<path> to C<val>.
1262 In the Augeas API, it is possible to clear a node by setting
1263 the value to NULL. Due to an oversight in the libguestfs API
1264 you cannot do that with this call. Instead you must use the
1265 C<guestfs_aug_clear> call.");
1267 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1268 [], (* XXX Augeas code needs tests. *)
1269 "insert a sibling Augeas node",
1271 Create a new sibling C<label> for C<path>, inserting it into
1272 the tree before or after C<path> (depending on the boolean
1275 C<path> must match exactly one existing node in the tree, and
1276 C<label> must be a label, ie. not contain C</>, C<*> or end
1277 with a bracketed index C<[N]>.");
1279 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1280 [], (* XXX Augeas code needs tests. *)
1281 "remove an Augeas path",
1283 Remove C<path> and all of its children.
1285 On success this returns the number of entries which were removed.");
1287 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1288 [], (* XXX Augeas code needs tests. *)
1291 Move the node C<src> to C<dest>. C<src> must match exactly
1292 one node. C<dest> is overwritten if it exists.");
1294 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1295 [], (* XXX Augeas code needs tests. *)
1296 "return Augeas nodes which match augpath",
1298 Returns a list of paths which match the path expression C<path>.
1299 The returned paths are sufficiently qualified so that they match
1300 exactly one node in the current tree.");
1302 ("aug_save", (RErr, []), 25, [Optional "augeas"],
1303 [], (* XXX Augeas code needs tests. *)
1304 "write all pending Augeas changes to disk",
1306 This writes all pending changes to disk.
1308 The flags which were passed to C<guestfs_aug_init> affect exactly
1309 how files are saved.");
1311 ("aug_load", (RErr, []), 27, [Optional "augeas"],
1312 [], (* XXX Augeas code needs tests. *)
1313 "load files into the tree",
1315 Load files into the tree.
1317 See C<aug_load> in the Augeas documentation for the full gory
1320 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1321 [], (* XXX Augeas code needs tests. *)
1322 "list Augeas nodes under augpath",
1324 This is just a shortcut for listing C<guestfs_aug_match>
1325 C<path/*> and sorting the resulting nodes into alphabetical order.");
1327 ("rm", (RErr, [Pathname "path"]), 29, [],
1328 [InitBasicFS, Always, TestRun
1331 InitBasicFS, Always, TestLastFail
1333 InitBasicFS, Always, TestLastFail
1338 Remove the single file C<path>.");
1340 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1341 [InitBasicFS, Always, TestRun
1344 InitBasicFS, Always, TestLastFail
1345 [["rmdir"; "/new"]];
1346 InitBasicFS, Always, TestLastFail
1348 ["rmdir"; "/new"]]],
1349 "remove a directory",
1351 Remove the single directory C<path>.");
1353 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1354 [InitBasicFS, Always, TestOutputFalse
1356 ["mkdir"; "/new/foo"];
1357 ["touch"; "/new/foo/bar"];
1359 ["exists"; "/new"]]],
1360 "remove a file or directory recursively",
1362 Remove the file or directory C<path>, recursively removing the
1363 contents if its a directory. This is like the C<rm -rf> shell
1366 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1367 [InitBasicFS, Always, TestOutputTrue
1369 ["is_dir"; "/new"]];
1370 InitBasicFS, Always, TestLastFail
1371 [["mkdir"; "/new/foo/bar"]]],
1372 "create a directory",
1374 Create a directory named C<path>.");
1376 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1377 [InitBasicFS, Always, TestOutputTrue
1378 [["mkdir_p"; "/new/foo/bar"];
1379 ["is_dir"; "/new/foo/bar"]];
1380 InitBasicFS, Always, TestOutputTrue
1381 [["mkdir_p"; "/new/foo/bar"];
1382 ["is_dir"; "/new/foo"]];
1383 InitBasicFS, Always, TestOutputTrue
1384 [["mkdir_p"; "/new/foo/bar"];
1385 ["is_dir"; "/new"]];
1386 (* Regression tests for RHBZ#503133: *)
1387 InitBasicFS, Always, TestRun
1389 ["mkdir_p"; "/new"]];
1390 InitBasicFS, Always, TestLastFail
1392 ["mkdir_p"; "/new"]]],
1393 "create a directory and parents",
1395 Create a directory named C<path>, creating any parent directories
1396 as necessary. This is like the C<mkdir -p> shell command.");
1398 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1399 [], (* XXX Need stat command to test *)
1402 Change the mode (permissions) of C<path> to C<mode>. Only
1403 numeric modes are supported.
1405 I<Note>: When using this command from guestfish, C<mode>
1406 by default would be decimal, unless you prefix it with
1407 C<0> to get octal, ie. use C<0700> not C<700>.
1409 The mode actually set is affected by the umask.");
1411 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1412 [], (* XXX Need stat command to test *)
1413 "change file owner and group",
1415 Change the file owner to C<owner> and group to C<group>.
1417 Only numeric uid and gid are supported. If you want to use
1418 names, you will need to locate and parse the password file
1419 yourself (Augeas support makes this relatively easy).");
1421 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1422 [InitISOFS, Always, TestOutputTrue (
1423 [["exists"; "/empty"]]);
1424 InitISOFS, Always, TestOutputTrue (
1425 [["exists"; "/directory"]])],
1426 "test if file or directory exists",
1428 This returns C<true> if and only if there is a file, directory
1429 (or anything) with the given C<path> name.
1431 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1433 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1434 [InitISOFS, Always, TestOutputTrue (
1435 [["is_file"; "/known-1"]]);
1436 InitISOFS, Always, TestOutputFalse (
1437 [["is_file"; "/directory"]])],
1438 "test if file exists",
1440 This returns C<true> if and only if there is a file
1441 with the given C<path> name. Note that it returns false for
1442 other objects like directories.
1444 See also C<guestfs_stat>.");
1446 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1447 [InitISOFS, Always, TestOutputFalse (
1448 [["is_dir"; "/known-3"]]);
1449 InitISOFS, Always, TestOutputTrue (
1450 [["is_dir"; "/directory"]])],
1451 "test if file exists",
1453 This returns C<true> if and only if there is a directory
1454 with the given C<path> name. Note that it returns false for
1455 other objects like files.
1457 See also C<guestfs_stat>.");
1459 ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1460 [InitEmpty, Always, TestOutputListOfDevices (
1461 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462 ["pvcreate"; "/dev/sda1"];
1463 ["pvcreate"; "/dev/sda2"];
1464 ["pvcreate"; "/dev/sda3"];
1465 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1466 "create an LVM physical volume",
1468 This creates an LVM physical volume on the named C<device>,
1469 where C<device> should usually be a partition name such
1472 ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [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 ["vgs"]], ["VG1"; "VG2"])],
1481 "create an LVM volume group",
1483 This creates an LVM volume group called C<volgroup>
1484 from the non-empty list of physical volumes C<physvols>.");
1486 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1487 [InitEmpty, Always, TestOutputList (
1488 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1489 ["pvcreate"; "/dev/sda1"];
1490 ["pvcreate"; "/dev/sda2"];
1491 ["pvcreate"; "/dev/sda3"];
1492 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1493 ["vgcreate"; "VG2"; "/dev/sda3"];
1494 ["lvcreate"; "LV1"; "VG1"; "50"];
1495 ["lvcreate"; "LV2"; "VG1"; "50"];
1496 ["lvcreate"; "LV3"; "VG2"; "50"];
1497 ["lvcreate"; "LV4"; "VG2"; "50"];
1498 ["lvcreate"; "LV5"; "VG2"; "50"];
1500 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1501 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1502 "create an LVM logical volume",
1504 This creates an LVM logical volume called C<logvol>
1505 on the volume group C<volgroup>, with C<size> megabytes.");
1507 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1508 [InitEmpty, Always, TestOutput (
1509 [["part_disk"; "/dev/sda"; "mbr"];
1510 ["mkfs"; "ext2"; "/dev/sda1"];
1511 ["mount_options"; ""; "/dev/sda1"; "/"];
1512 ["write"; "/new"; "new file contents"];
1513 ["cat"; "/new"]], "new file contents")],
1514 "make a filesystem",
1516 This creates a filesystem on C<device> (usually a partition
1517 or LVM logical volume). The filesystem type is C<fstype>, for
1520 ("sfdisk", (RErr, [Device "device";
1521 Int "cyls"; Int "heads"; Int "sectors";
1522 StringList "lines"]), 43, [DangerWillRobinson],
1524 "create partitions on a block device",
1526 This is a direct interface to the L<sfdisk(8)> program for creating
1527 partitions on block devices.
1529 C<device> should be a block device, for example C</dev/sda>.
1531 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1532 and sectors on the device, which are passed directly to sfdisk as
1533 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1534 of these, then the corresponding parameter is omitted. Usually for
1535 'large' disks, you can just pass C<0> for these, but for small
1536 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1537 out the right geometry and you will need to tell it.
1539 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1540 information refer to the L<sfdisk(8)> manpage.
1542 To create a single partition occupying the whole disk, you would
1543 pass C<lines> as a single element list, when the single element being
1544 the string C<,> (comma).
1546 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1547 C<guestfs_part_init>");
1549 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1550 (* Regression test for RHBZ#597135. *)
1551 [InitBasicFS, Always, TestLastFail
1552 [["write_file"; "/new"; "abc"; "10000"]]],
1555 This call creates a file called C<path>. The contents of the
1556 file is the string C<content> (which can contain any 8 bit data),
1557 with length C<size>.
1559 As a special case, if C<size> is C<0>
1560 then the length is calculated using C<strlen> (so in this case
1561 the content cannot contain embedded ASCII NULs).
1563 I<NB.> Owing to a bug, writing content containing ASCII NUL
1564 characters does I<not> work, even if the length is specified.");
1566 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567 [InitEmpty, Always, TestOutputListOfDevices (
1568 [["part_disk"; "/dev/sda"; "mbr"];
1569 ["mkfs"; "ext2"; "/dev/sda1"];
1570 ["mount_options"; ""; "/dev/sda1"; "/"];
1571 ["mounts"]], ["/dev/sda1"]);
1572 InitEmpty, Always, TestOutputList (
1573 [["part_disk"; "/dev/sda"; "mbr"];
1574 ["mkfs"; "ext2"; "/dev/sda1"];
1575 ["mount_options"; ""; "/dev/sda1"; "/"];
1578 "unmount a filesystem",
1580 This unmounts the given filesystem. The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1584 ("mounts", (RStringList "devices", []), 46, [],
1585 [InitBasicFS, Always, TestOutputListOfDevices (
1586 [["mounts"]], ["/dev/sda1"])],
1587 "show mounted filesystems",
1589 This returns the list of currently mounted filesystems. It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592 Some internal mounts are not shown.
1594 See also: C<guestfs_mountpoints>");
1596 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597 [InitBasicFS, Always, TestOutputList (
1600 (* check that umount_all can unmount nested mounts correctly: *)
1601 InitEmpty, Always, TestOutputList (
1602 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603 ["mkfs"; "ext2"; "/dev/sda1"];
1604 ["mkfs"; "ext2"; "/dev/sda2"];
1605 ["mkfs"; "ext2"; "/dev/sda3"];
1606 ["mount_options"; ""; "/dev/sda1"; "/"];
1608 ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609 ["mkdir"; "/mp1/mp2"];
1610 ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611 ["mkdir"; "/mp1/mp2/mp3"];
1614 "unmount all filesystems",
1616 This unmounts all mounted filesystems.
1618 Some internal mounts are not unmounted by this call.");
1620 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622 "remove all LVM LVs, VGs and PVs",
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1627 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628 [InitISOFS, Always, TestOutput (
1629 [["file"; "/empty"]], "empty");
1630 InitISOFS, Always, TestOutput (
1631 [["file"; "/known-1"]], "ASCII text");
1632 InitISOFS, Always, TestLastFail (
1633 [["file"; "/notexists"]]);
1634 InitISOFS, Always, TestOutput (
1635 [["file"; "/abssymlink"]], "symbolic link");
1636 InitISOFS, Always, TestOutput (
1637 [["file"; "/directory"]], "directory")],
1638 "determine file type",
1640 This call uses the standard L<file(1)> command to determine
1641 the type or contents of the file.
1643 This call will also transparently look inside various types
1646 The exact command which runs is C<file -zb path>. Note in
1647 particular that the filename is not prepended to the output
1650 This command can also be used on C</dev/> devices
1651 (and partitions, LV names). You can for example use this
1652 to determine if a device contains a filesystem, although
1653 it's usually better to use C<guestfs_vfs_type>.
1655 If the C<path> does not begin with C</dev/> then
1656 this command only works for the content of regular files.
1657 For other file types (directory, symbolic link etc) it
1658 will just return the string C<directory> etc.");
1660 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1661 [InitBasicFS, Always, TestOutput (
1662 [["upload"; "test-command"; "/test-command"];
1663 ["chmod"; "0o755"; "/test-command"];
1664 ["command"; "/test-command 1"]], "Result1");
1665 InitBasicFS, Always, TestOutput (
1666 [["upload"; "test-command"; "/test-command"];
1667 ["chmod"; "0o755"; "/test-command"];
1668 ["command"; "/test-command 2"]], "Result2\n");
1669 InitBasicFS, Always, TestOutput (
1670 [["upload"; "test-command"; "/test-command"];
1671 ["chmod"; "0o755"; "/test-command"];
1672 ["command"; "/test-command 3"]], "\nResult3");
1673 InitBasicFS, Always, TestOutput (
1674 [["upload"; "test-command"; "/test-command"];
1675 ["chmod"; "0o755"; "/test-command"];
1676 ["command"; "/test-command 4"]], "\nResult4\n");
1677 InitBasicFS, Always, TestOutput (
1678 [["upload"; "test-command"; "/test-command"];
1679 ["chmod"; "0o755"; "/test-command"];
1680 ["command"; "/test-command 5"]], "\nResult5\n\n");
1681 InitBasicFS, Always, TestOutput (
1682 [["upload"; "test-command"; "/test-command"];
1683 ["chmod"; "0o755"; "/test-command"];
1684 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1685 InitBasicFS, Always, TestOutput (
1686 [["upload"; "test-command"; "/test-command"];
1687 ["chmod"; "0o755"; "/test-command"];
1688 ["command"; "/test-command 7"]], "");
1689 InitBasicFS, Always, TestOutput (
1690 [["upload"; "test-command"; "/test-command"];
1691 ["chmod"; "0o755"; "/test-command"];
1692 ["command"; "/test-command 8"]], "\n");
1693 InitBasicFS, Always, TestOutput (
1694 [["upload"; "test-command"; "/test-command"];
1695 ["chmod"; "0o755"; "/test-command"];
1696 ["command"; "/test-command 9"]], "\n\n");
1697 InitBasicFS, Always, TestOutput (
1698 [["upload"; "test-command"; "/test-command"];
1699 ["chmod"; "0o755"; "/test-command"];
1700 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1701 InitBasicFS, Always, TestOutput (
1702 [["upload"; "test-command"; "/test-command"];
1703 ["chmod"; "0o755"; "/test-command"];
1704 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1705 InitBasicFS, Always, TestLastFail (
1706 [["upload"; "test-command"; "/test-command"];
1707 ["chmod"; "0o755"; "/test-command"];
1708 ["command"; "/test-command"]])],
1709 "run a command from the guest filesystem",
1711 This call runs a command from the guest filesystem. The
1712 filesystem must be mounted, and must contain a compatible
1713 operating system (ie. something Linux, with the same
1714 or compatible processor architecture).
1716 The single parameter is an argv-style list of arguments.
1717 The first element is the name of the program to run.
1718 Subsequent elements are parameters. The list must be
1719 non-empty (ie. must contain a program name). Note that
1720 the command runs directly, and is I<not> invoked via
1721 the shell (see C<guestfs_sh>).
1723 The return value is anything printed to I<stdout> by
1726 If the command returns a non-zero exit status, then
1727 this function returns an error message. The error message
1728 string is the content of I<stderr> from the command.
1730 The C<$PATH> environment variable will contain at least
1731 C</usr/bin> and C</bin>. If you require a program from
1732 another location, you should provide the full path in the
1735 Shared libraries and data files required by the program
1736 must be available on filesystems which are mounted in the
1737 correct places. It is the caller's responsibility to ensure
1738 all filesystems that are needed are mounted at the right
1741 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1742 [InitBasicFS, Always, TestOutputList (
1743 [["upload"; "test-command"; "/test-command"];
1744 ["chmod"; "0o755"; "/test-command"];
1745 ["command_lines"; "/test-command 1"]], ["Result1"]);
1746 InitBasicFS, Always, TestOutputList (
1747 [["upload"; "test-command"; "/test-command"];
1748 ["chmod"; "0o755"; "/test-command"];
1749 ["command_lines"; "/test-command 2"]], ["Result2"]);
1750 InitBasicFS, Always, TestOutputList (
1751 [["upload"; "test-command"; "/test-command"];
1752 ["chmod"; "0o755"; "/test-command"];
1753 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1754 InitBasicFS, Always, TestOutputList (
1755 [["upload"; "test-command"; "/test-command"];
1756 ["chmod"; "0o755"; "/test-command"];
1757 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1758 InitBasicFS, Always, TestOutputList (
1759 [["upload"; "test-command"; "/test-command"];
1760 ["chmod"; "0o755"; "/test-command"];
1761 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1762 InitBasicFS, Always, TestOutputList (
1763 [["upload"; "test-command"; "/test-command"];
1764 ["chmod"; "0o755"; "/test-command"];
1765 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1766 InitBasicFS, Always, TestOutputList (
1767 [["upload"; "test-command"; "/test-command"];
1768 ["chmod"; "0o755"; "/test-command"];
1769 ["command_lines"; "/test-command 7"]], []);
1770 InitBasicFS, Always, TestOutputList (
1771 [["upload"; "test-command"; "/test-command"];
1772 ["chmod"; "0o755"; "/test-command"];
1773 ["command_lines"; "/test-command 8"]], [""]);
1774 InitBasicFS, Always, TestOutputList (
1775 [["upload"; "test-command"; "/test-command"];
1776 ["chmod"; "0o755"; "/test-command"];
1777 ["command_lines"; "/test-command 9"]], ["";""]);
1778 InitBasicFS, Always, TestOutputList (
1779 [["upload"; "test-command"; "/test-command"];
1780 ["chmod"; "0o755"; "/test-command"];
1781 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1782 InitBasicFS, Always, TestOutputList (
1783 [["upload"; "test-command"; "/test-command"];
1784 ["chmod"; "0o755"; "/test-command"];
1785 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1786 "run a command, returning lines",
1788 This is the same as C<guestfs_command>, but splits the
1789 result into a list of lines.
1791 See also: C<guestfs_sh_lines>");
1793 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1794 [InitISOFS, Always, TestOutputStruct (
1795 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1796 "get file information",
1798 Returns file information for the given C<path>.
1800 This is the same as the C<stat(2)> system call.");
1802 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1803 [InitISOFS, Always, TestOutputStruct (
1804 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1805 "get file information for a symbolic link",
1807 Returns file information for the given C<path>.
1809 This is the same as C<guestfs_stat> except that if C<path>
1810 is a symbolic link, then the link is stat-ed, not the file it
1813 This is the same as the C<lstat(2)> system call.");
1815 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1816 [InitISOFS, Always, TestOutputStruct (
1817 [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1818 "get file system statistics",
1820 Returns file system statistics for any mounted file system.
1821 C<path> should be a file or directory in the mounted file system
1822 (typically it is the mount point itself, but it doesn't need to be).
1824 This is the same as the C<statvfs(2)> system call.");
1826 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1828 "get ext2/ext3/ext4 superblock details",
1830 This returns the contents of the ext2, ext3 or ext4 filesystem
1831 superblock on C<device>.
1833 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1834 manpage for more details. The list of fields returned isn't
1835 clearly defined, and depends on both the version of C<tune2fs>
1836 that libguestfs was built against, and the filesystem itself.");
1838 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1839 [InitEmpty, Always, TestOutputTrue (
1840 [["blockdev_setro"; "/dev/sda"];
1841 ["blockdev_getro"; "/dev/sda"]])],
1842 "set block device to read-only",
1844 Sets the block device named C<device> to read-only.
1846 This uses the L<blockdev(8)> command.");
1848 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1849 [InitEmpty, Always, TestOutputFalse (
1850 [["blockdev_setrw"; "/dev/sda"];
1851 ["blockdev_getro"; "/dev/sda"]])],
1852 "set block device to read-write",
1854 Sets the block device named C<device> to read-write.
1856 This uses the L<blockdev(8)> command.");
1858 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1859 [InitEmpty, Always, TestOutputTrue (
1860 [["blockdev_setro"; "/dev/sda"];
1861 ["blockdev_getro"; "/dev/sda"]])],
1862 "is block device set to read-only",
1864 Returns a boolean indicating if the block device is read-only
1865 (true if read-only, false if not).
1867 This uses the L<blockdev(8)> command.");
1869 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1870 [InitEmpty, Always, TestOutputInt (
1871 [["blockdev_getss"; "/dev/sda"]], 512)],
1872 "get sectorsize of block device",
1874 This returns the size of sectors on a block device.
1875 Usually 512, but can be larger for modern devices.
1877 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1880 This uses the L<blockdev(8)> command.");
1882 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1883 [InitEmpty, Always, TestOutputInt (
1884 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1885 "get blocksize of block device",
1887 This returns the block size of a device.
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1892 This uses the L<blockdev(8)> command.");
1894 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1896 "set blocksize of block device",
1898 This sets the block size of a device.
1900 (Note this is different from both I<size in blocks> and
1901 I<filesystem block size>).
1903 This uses the L<blockdev(8)> command.");
1905 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1906 [InitEmpty, Always, TestOutputInt (
1907 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1908 "get total size of device in 512-byte sectors",
1910 This returns the size of the device in units of 512-byte sectors
1911 (even if the sectorsize isn't 512 bytes ... weird).
1913 See also C<guestfs_blockdev_getss> for the real sector size of
1914 the device, and C<guestfs_blockdev_getsize64> for the more
1915 useful I<size in bytes>.
1917 This uses the L<blockdev(8)> command.");
1919 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1920 [InitEmpty, Always, TestOutputInt (
1921 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1922 "get total size of device in bytes",
1924 This returns the size of the device in bytes.
1926 See also C<guestfs_blockdev_getsz>.
1928 This uses the L<blockdev(8)> command.");
1930 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1931 [InitEmpty, Always, TestRun
1932 [["blockdev_flushbufs"; "/dev/sda"]]],
1933 "flush device buffers",
1935 This tells the kernel to flush internal buffers associated
1938 This uses the L<blockdev(8)> command.");
1940 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1941 [InitEmpty, Always, TestRun
1942 [["blockdev_rereadpt"; "/dev/sda"]]],
1943 "reread partition table",
1945 Reread the partition table on C<device>.
1947 This uses the L<blockdev(8)> command.");
1949 ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1950 [InitBasicFS, Always, TestOutput (
1951 (* Pick a file from cwd which isn't likely to change. *)
1952 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1953 ["checksum"; "md5"; "/COPYING.LIB"]],
1954 Digest.to_hex (Digest.file "COPYING.LIB"))],
1955 "upload a file from the local machine",
1957 Upload local file C<filename> to C<remotefilename> on the
1960 C<filename> can also be a named pipe.
1962 See also C<guestfs_download>.");
1964 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1965 [InitBasicFS, Always, TestOutput (
1966 (* Pick a file from cwd which isn't likely to change. *)
1967 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1968 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1969 ["upload"; "testdownload.tmp"; "/upload"];
1970 ["checksum"; "md5"; "/upload"]],
1971 Digest.to_hex (Digest.file "COPYING.LIB"))],
1972 "download a file to the local machine",
1974 Download file C<remotefilename> and save it as C<filename>
1975 on the local machine.
1977 C<filename> can also be a named pipe.
1979 See also C<guestfs_upload>, C<guestfs_cat>.");
1981 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1982 [InitISOFS, Always, TestOutput (
1983 [["checksum"; "crc"; "/known-3"]], "2891671662");
1984 InitISOFS, Always, TestLastFail (
1985 [["checksum"; "crc"; "/notexists"]]);
1986 InitISOFS, Always, TestOutput (
1987 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1988 InitISOFS, Always, TestOutput (
1989 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1990 InitISOFS, Always, TestOutput (
1991 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1992 InitISOFS, Always, TestOutput (
1993 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1994 InitISOFS, Always, TestOutput (
1995 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1996 InitISOFS, Always, TestOutput (
1997 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1998 (* Test for RHBZ#579608, absolute symbolic links. *)
1999 InitISOFS, Always, TestOutput (
2000 [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2001 "compute MD5, SHAx or CRC checksum of file",
2003 This call computes the MD5, SHAx or CRC checksum of the
2006 The type of checksum to compute is given by the C<csumtype>
2007 parameter which must have one of the following values:
2013 Compute the cyclic redundancy check (CRC) specified by POSIX
2014 for the C<cksum> command.
2018 Compute the MD5 hash (using the C<md5sum> program).
2022 Compute the SHA1 hash (using the C<sha1sum> program).
2026 Compute the SHA224 hash (using the C<sha224sum> program).
2030 Compute the SHA256 hash (using the C<sha256sum> program).
2034 Compute the SHA384 hash (using the C<sha384sum> program).
2038 Compute the SHA512 hash (using the C<sha512sum> program).
2042 The checksum is returned as a printable string.
2044 To get the checksum for a device, use C<guestfs_checksum_device>.
2046 To get the checksums for many files, use C<guestfs_checksums_out>.");
2048 ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2049 [InitBasicFS, Always, TestOutput (
2050 [["tar_in"; "../images/helloworld.tar"; "/"];
2051 ["cat"; "/hello"]], "hello\n")],
2052 "unpack tarfile to directory",
2054 This command uploads and unpacks local file C<tarfile> (an
2055 I<uncompressed> tar file) into C<directory>.
2057 To upload a compressed tarball, use C<guestfs_tgz_in>
2058 or C<guestfs_txz_in>.");
2060 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2062 "pack directory into tarfile",
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarfile>.
2067 To download a compressed tarball, use C<guestfs_tgz_out>
2068 or C<guestfs_txz_out>.");
2070 ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2071 [InitBasicFS, Always, TestOutput (
2072 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2073 ["cat"; "/hello"]], "hello\n")],
2074 "unpack compressed tarball to directory",
2076 This command uploads and unpacks local file C<tarball> (a
2077 I<gzip compressed> tar file) into C<directory>.
2079 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2081 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2083 "pack directory into compressed tarball",
2085 This command packs the contents of C<directory> and downloads
2086 it to local file C<tarball>.
2088 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2090 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2091 [InitBasicFS, Always, TestLastFail (
2093 ["mount_ro"; "/dev/sda1"; "/"];
2094 ["touch"; "/new"]]);
2095 InitBasicFS, Always, TestOutput (
2096 [["write"; "/new"; "data"];
2098 ["mount_ro"; "/dev/sda1"; "/"];
2099 ["cat"; "/new"]], "data")],
2100 "mount a guest disk, read-only",
2102 This is the same as the C<guestfs_mount> command, but it
2103 mounts the filesystem with the read-only (I<-o ro>) flag.");
2105 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2107 "mount a guest disk with mount options",
2109 This is the same as the C<guestfs_mount> command, but it
2110 allows you to set the mount options as for the
2111 L<mount(8)> I<-o> flag.
2113 If the C<options> parameter is an empty string, then
2114 no options are passed (all options default to whatever
2115 the filesystem uses).");
2117 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2119 "mount a guest disk with mount options and vfstype",
2121 This is the same as the C<guestfs_mount> command, but it
2122 allows you to set both the mount options and the vfstype
2123 as for the L<mount(8)> I<-o> and I<-t> flags.");
2125 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2127 "debugging and internals",
2129 The C<guestfs_debug> command exposes some internals of
2130 C<guestfsd> (the guestfs daemon) that runs inside the
2133 There is no comprehensive help for this command. You have
2134 to look at the file C<daemon/debug.c> in the libguestfs source
2135 to find out what you can do.");
2137 ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2138 [InitEmpty, Always, TestOutputList (
2139 [["part_disk"; "/dev/sda"; "mbr"];
2140 ["pvcreate"; "/dev/sda1"];
2141 ["vgcreate"; "VG"; "/dev/sda1"];
2142 ["lvcreate"; "LV1"; "VG"; "50"];
2143 ["lvcreate"; "LV2"; "VG"; "50"];
2144 ["lvremove"; "/dev/VG/LV1"];
2145 ["lvs"]], ["/dev/VG/LV2"]);
2146 InitEmpty, Always, TestOutputList (
2147 [["part_disk"; "/dev/sda"; "mbr"];
2148 ["pvcreate"; "/dev/sda1"];
2149 ["vgcreate"; "VG"; "/dev/sda1"];
2150 ["lvcreate"; "LV1"; "VG"; "50"];
2151 ["lvcreate"; "LV2"; "VG"; "50"];
2152 ["lvremove"; "/dev/VG"];
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"];
2160 ["lvremove"; "/dev/VG"];
2162 "remove an LVM logical volume",
2164 Remove an LVM logical volume C<device>, where C<device> is
2165 the path to the LV, such as C</dev/VG/LV>.
2167 You can also remove all LVs in a volume group by specifying
2168 the VG name, C</dev/VG>.");
2170 ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2171 [InitEmpty, Always, TestOutputList (
2172 [["part_disk"; "/dev/sda"; "mbr"];
2173 ["pvcreate"; "/dev/sda1"];
2174 ["vgcreate"; "VG"; "/dev/sda1"];
2175 ["lvcreate"; "LV1"; "VG"; "50"];
2176 ["lvcreate"; "LV2"; "VG"; "50"];
2179 InitEmpty, Always, TestOutputList (
2180 [["part_disk"; "/dev/sda"; "mbr"];
2181 ["pvcreate"; "/dev/sda1"];
2182 ["vgcreate"; "VG"; "/dev/sda1"];
2183 ["lvcreate"; "LV1"; "VG"; "50"];
2184 ["lvcreate"; "LV2"; "VG"; "50"];
2187 "remove an LVM volume group",
2189 Remove an LVM volume group C<vgname>, (for example C<VG>).
2191 This also forcibly removes all logical volumes in the volume
2194 ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2195 [InitEmpty, Always, TestOutputListOfDevices (
2196 [["part_disk"; "/dev/sda"; "mbr"];
2197 ["pvcreate"; "/dev/sda1"];
2198 ["vgcreate"; "VG"; "/dev/sda1"];
2199 ["lvcreate"; "LV1"; "VG"; "50"];
2200 ["lvcreate"; "LV2"; "VG"; "50"];
2202 ["pvremove"; "/dev/sda1"];
2204 InitEmpty, Always, TestOutputListOfDevices (
2205 [["part_disk"; "/dev/sda"; "mbr"];
2206 ["pvcreate"; "/dev/sda1"];
2207 ["vgcreate"; "VG"; "/dev/sda1"];
2208 ["lvcreate"; "LV1"; "VG"; "50"];
2209 ["lvcreate"; "LV2"; "VG"; "50"];
2211 ["pvremove"; "/dev/sda1"];
2213 InitEmpty, Always, TestOutputListOfDevices (
2214 [["part_disk"; "/dev/sda"; "mbr"];
2215 ["pvcreate"; "/dev/sda1"];
2216 ["vgcreate"; "VG"; "/dev/sda1"];
2217 ["lvcreate"; "LV1"; "VG"; "50"];
2218 ["lvcreate"; "LV2"; "VG"; "50"];
2220 ["pvremove"; "/dev/sda1"];
2222 "remove an LVM physical volume",
2224 This wipes a physical volume C<device> so that LVM will no longer
2227 The implementation uses the C<pvremove> command which refuses to
2228 wipe physical volumes that contain any volume groups, so you have
2229 to remove those first.");
2231 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2232 [InitBasicFS, Always, TestOutput (
2233 [["set_e2label"; "/dev/sda1"; "testlabel"];
2234 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2235 "set the ext2/3/4 filesystem label",
2237 This sets the ext2/3/4 filesystem label of the filesystem on
2238 C<device> to C<label>. Filesystem labels are limited to
2241 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2242 to return the existing label on a filesystem.");
2244 ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2246 "get the ext2/3/4 filesystem label",
2248 This returns the ext2/3/4 filesystem label of the filesystem on
2251 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2252 (let uuid = uuidgen () in
2253 [InitBasicFS, Always, TestOutput (
2254 [["set_e2uuid"; "/dev/sda1"; uuid];
2255 ["get_e2uuid"; "/dev/sda1"]], uuid);
2256 InitBasicFS, Always, TestOutput (
2257 [["set_e2uuid"; "/dev/sda1"; "clear"];
2258 ["get_e2uuid"; "/dev/sda1"]], "");
2259 (* We can't predict what UUIDs will be, so just check the commands run. *)
2260 InitBasicFS, Always, TestRun (
2261 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2262 InitBasicFS, Always, TestRun (
2263 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2264 "set the ext2/3/4 filesystem UUID",
2266 This sets the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device> to C<uuid>. The format of the UUID and alternatives
2268 such as C<clear>, C<random> and C<time> are described in the
2269 L<tune2fs(8)> manpage.
2271 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2272 to return the existing UUID of a filesystem.");
2274 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2275 (* Regression test for RHBZ#597112. *)
2276 (let uuid = uuidgen () in
2277 [InitBasicFS, Always, TestOutput (
2278 [["mke2journal"; "1024"; "/dev/sdb"];
2279 ["set_e2uuid"; "/dev/sdb"; uuid];
2280 ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2281 "get the ext2/3/4 filesystem UUID",
2283 This returns the ext2/3/4 filesystem UUID of the filesystem on
2286 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2287 [InitBasicFS, Always, TestOutputInt (
2288 [["umount"; "/dev/sda1"];
2289 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2290 InitBasicFS, Always, TestOutputInt (
2291 [["umount"; "/dev/sda1"];
2292 ["zero"; "/dev/sda1"];
2293 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2294 "run the filesystem checker",
2296 This runs the filesystem checker (fsck) on C<device> which
2297 should have filesystem type C<fstype>.
2299 The returned integer is the status. See L<fsck(8)> for the
2300 list of status codes from C<fsck>.
2308 Multiple status codes can be summed together.
2312 A non-zero return code can mean \"success\", for example if
2313 errors have been corrected on the filesystem.
2317 Checking or repairing NTFS volumes is not supported
2322 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2324 ("zero", (RErr, [Device "device"]), 85, [],
2325 [InitBasicFS, Always, TestOutput (
2326 [["umount"; "/dev/sda1"];
2327 ["zero"; "/dev/sda1"];
2328 ["file"; "/dev/sda1"]], "data")],
2329 "write zeroes to the device",
2331 This command writes zeroes over the first few blocks of C<device>.
2333 How many blocks are zeroed isn't specified (but it's I<not> enough
2334 to securely wipe the device). It should be sufficient to remove
2335 any partition tables, filesystem superblocks and so on.
2337 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2339 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2341 * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2342 * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2344 [InitBasicFS, Always, TestOutputTrue (
2345 [["mkdir_p"; "/boot/grub"];
2346 ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2347 ["grub_install"; "/"; "/dev/vda"];
2348 ["is_dir"; "/boot"]])],
2351 This command installs GRUB (the Grand Unified Bootloader) on
2352 C<device>, with the root directory being C<root>.
2354 Note: If grub-install reports the error
2355 \"No suitable drive was found in the generated device map.\"
2356 it may be that you need to create a C</boot/grub/device.map>
2357 file first that contains the mapping between grub device names
2358 and Linux device names. It is usually sufficient to create
2363 replacing C</dev/vda> with the name of the installation device.");
2365 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2366 [InitBasicFS, Always, TestOutput (
2367 [["write"; "/old"; "file content"];
2368 ["cp"; "/old"; "/new"];
2369 ["cat"; "/new"]], "file content");
2370 InitBasicFS, Always, TestOutputTrue (
2371 [["write"; "/old"; "file content"];
2372 ["cp"; "/old"; "/new"];
2373 ["is_file"; "/old"]]);
2374 InitBasicFS, Always, TestOutput (
2375 [["write"; "/old"; "file content"];
2377 ["cp"; "/old"; "/dir/new"];
2378 ["cat"; "/dir/new"]], "file content")],
2381 This copies a file from C<src> to C<dest> where C<dest> is
2382 either a destination filename or destination directory.");
2384 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2385 [InitBasicFS, Always, TestOutput (
2386 [["mkdir"; "/olddir"];
2387 ["mkdir"; "/newdir"];
2388 ["write"; "/olddir/file"; "file content"];
2389 ["cp_a"; "/olddir"; "/newdir"];
2390 ["cat"; "/newdir/olddir/file"]], "file content")],
2391 "copy a file or directory recursively",
2393 This copies a file or directory from C<src> to C<dest>
2394 recursively using the C<cp -a> command.");
2396 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2397 [InitBasicFS, Always, TestOutput (
2398 [["write"; "/old"; "file content"];
2399 ["mv"; "/old"; "/new"];
2400 ["cat"; "/new"]], "file content");
2401 InitBasicFS, Always, TestOutputFalse (
2402 [["write"; "/old"; "file content"];
2403 ["mv"; "/old"; "/new"];
2404 ["is_file"; "/old"]])],
2407 This moves a file from C<src> to C<dest> where C<dest> is
2408 either a destination filename or destination directory.");
2410 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2411 [InitEmpty, Always, TestRun (
2412 [["drop_caches"; "3"]])],
2413 "drop kernel page cache, dentries and inodes",
2415 This instructs the guest kernel to drop its page cache,
2416 and/or dentries and inode caches. The parameter C<whattodrop>
2417 tells the kernel what precisely to drop, see
2418 L<http://linux-mm.org/Drop_Caches>
2420 Setting C<whattodrop> to 3 should drop everything.
2422 This automatically calls L<sync(2)> before the operation,
2423 so that the maximum guest memory is freed.");
2425 ("dmesg", (RString "kmsgs", []), 91, [],
2426 [InitEmpty, Always, TestRun (
2428 "return kernel messages",
2430 This returns the kernel messages (C<dmesg> output) from
2431 the guest kernel. This is sometimes useful for extended
2432 debugging of problems.
2434 Another way to get the same information is to enable
2435 verbose messages with C<guestfs_set_verbose> or by setting
2436 the environment variable C<LIBGUESTFS_DEBUG=1> before
2437 running the program.");
2439 ("ping_daemon", (RErr, []), 92, [],
2440 [InitEmpty, Always, TestRun (
2441 [["ping_daemon"]])],
2442 "ping the guest daemon",
2444 This is a test probe into the guestfs daemon running inside
2445 the qemu subprocess. Calling this function checks that the
2446 daemon responds to the ping message, without affecting the daemon
2447 or attached block device(s) in any other way.");
2449 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2450 [InitBasicFS, Always, TestOutputTrue (
2451 [["write"; "/file1"; "contents of a file"];
2452 ["cp"; "/file1"; "/file2"];
2453 ["equal"; "/file1"; "/file2"]]);
2454 InitBasicFS, Always, TestOutputFalse (
2455 [["write"; "/file1"; "contents of a file"];
2456 ["write"; "/file2"; "contents of another file"];
2457 ["equal"; "/file1"; "/file2"]]);
2458 InitBasicFS, Always, TestLastFail (
2459 [["equal"; "/file1"; "/file2"]])],
2460 "test if two files have equal contents",
2462 This compares the two files C<file1> and C<file2> and returns
2463 true if their content is exactly equal, or false otherwise.
2465 The external L<cmp(1)> program is used for the comparison.");
2467 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2468 [InitISOFS, Always, TestOutputList (
2469 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2470 InitISOFS, Always, TestOutputList (
2471 [["strings"; "/empty"]], []);
2472 (* Test for RHBZ#579608, absolute symbolic links. *)
2473 InitISOFS, Always, TestRun (
2474 [["strings"; "/abssymlink"]])],
2475 "print the printable strings in a file",
2477 This runs the L<strings(1)> command on a file and returns
2478 the list of printable strings found.");
2480 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2481 [InitISOFS, Always, TestOutputList (
2482 [["strings_e"; "b"; "/known-5"]], []);
2483 InitBasicFS, Always, TestOutputList (
2484 [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2485 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2486 "print the printable strings in a file",
2488 This is like the C<guestfs_strings> command, but allows you to
2489 specify the encoding of strings that are looked for in
2490 the source file C<path>.
2492 Allowed encodings are:
2498 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2499 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2503 Single 8-bit-byte characters.
2507 16-bit big endian strings such as those encoded in
2508 UTF-16BE or UCS-2BE.
2510 =item l (lower case letter L)
2512 16-bit little endian such as UTF-16LE and UCS-2LE.
2513 This is useful for examining binaries in Windows guests.
2517 32-bit big endian such as UCS-4BE.
2521 32-bit little endian such as UCS-4LE.
2525 The returned strings are transcoded to UTF-8.");
2527 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2528 [InitISOFS, Always, TestOutput (
2529 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2530 (* Test for RHBZ#501888c2 regression which caused large hexdump
2531 * commands to segfault.
2533 InitISOFS, Always, TestRun (
2534 [["hexdump"; "/100krandom"]]);
2535 (* Test for RHBZ#579608, absolute symbolic links. *)
2536 InitISOFS, Always, TestRun (
2537 [["hexdump"; "/abssymlink"]])],
2538 "dump a file in hexadecimal",
2540 This runs C<hexdump -C> on the given C<path>. The result is
2541 the human-readable, canonical hex dump of the file.");
2543 ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2544 [InitNone, Always, TestOutput (
2545 [["part_disk"; "/dev/sda"; "mbr"];
2546 ["mkfs"; "ext3"; "/dev/sda1"];
2547 ["mount_options"; ""; "/dev/sda1"; "/"];
2548 ["write"; "/new"; "test file"];
2549 ["umount"; "/dev/sda1"];
2550 ["zerofree"; "/dev/sda1"];
2551 ["mount_options"; ""; "/dev/sda1"; "/"];
2552 ["cat"; "/new"]], "test file")],
2553 "zero unused inodes and disk blocks on ext2/3 filesystem",
2555 This runs the I<zerofree> program on C<device>. This program
2556 claims to zero unused inodes and disk blocks on an ext2/3
2557 filesystem, thus making it possible to compress the filesystem
2560 You should B<not> run this program if the filesystem is
2563 It is possible that using this program can damage the filesystem
2564 or data on the filesystem.");
2566 ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2568 "resize an LVM physical volume",
2570 This resizes (expands or shrinks) an existing LVM physical
2571 volume to match the new size of the underlying device.");
2573 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2574 Int "cyls"; Int "heads"; Int "sectors";
2575 String "line"]), 99, [DangerWillRobinson],
2577 "modify a single partition on a block device",
2579 This runs L<sfdisk(8)> option to modify just the single
2580 partition C<n> (note: C<n> counts from 1).
2582 For other parameters, see C<guestfs_sfdisk>. You should usually
2583 pass C<0> for the cyls/heads/sectors parameters.
2585 See also: C<guestfs_part_add>");
2587 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2589 "display the partition table",
2591 This displays the partition table on C<device>, in the
2592 human-readable output of the L<sfdisk(8)> command. It is
2593 not intended to be parsed.
2595 See also: C<guestfs_part_list>");
2597 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2599 "display the kernel geometry",
2601 This displays the kernel's idea of the geometry of C<device>.
2603 The result is in human-readable format, and not designed to
2606 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2608 "display the disk geometry from the partition table",
2610 This displays the disk geometry of C<device> read from the
2611 partition table. Especially in the case where the underlying
2612 block device has been resized, this can be different from the
2613 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2615 The result is in human-readable format, and not designed to
2618 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2620 "activate or deactivate all volume groups",
2622 This command activates or (if C<activate> is false) deactivates
2623 all logical volumes in all volume groups.
2624 If activated, then they are made known to the
2625 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2626 then those devices disappear.
2628 This command is the same as running C<vgchange -a y|n>");
2630 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2632 "activate or deactivate some volume groups",
2634 This command activates or (if C<activate> is false) deactivates
2635 all logical volumes in the listed volume groups C<volgroups>.
2636 If activated, then they are made known to the
2637 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2638 then those devices disappear.
2640 This command is the same as running C<vgchange -a y|n volgroups...>
2642 Note that if C<volgroups> is an empty list then B<all> volume groups
2643 are activated or deactivated.");
2645 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2646 [InitNone, Always, TestOutput (
2647 [["part_disk"; "/dev/sda"; "mbr"];
2648 ["pvcreate"; "/dev/sda1"];
2649 ["vgcreate"; "VG"; "/dev/sda1"];
2650 ["lvcreate"; "LV"; "VG"; "10"];
2651 ["mkfs"; "ext2"; "/dev/VG/LV"];
2652 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2653 ["write"; "/new"; "test content"];
2655 ["lvresize"; "/dev/VG/LV"; "20"];
2656 ["e2fsck_f"; "/dev/VG/LV"];
2657 ["resize2fs"; "/dev/VG/LV"];
2658 ["mount_options"; ""; "/dev/VG/LV"; "/"];
2659 ["cat"; "/new"]], "test content");
2660 InitNone, Always, TestRun (
2661 (* Make an LV smaller to test RHBZ#587484. *)
2662 [["part_disk"; "/dev/sda"; "mbr"];
2663 ["pvcreate"; "/dev/sda1"];
2664 ["vgcreate"; "VG"; "/dev/sda1"];
2665 ["lvcreate"; "LV"; "VG"; "20"];
2666 ["lvresize"; "/dev/VG/LV"; "10"]])],
2667 "resize an LVM logical volume",
2669 This resizes (expands or shrinks) an existing LVM logical
2670 volume to C<mbytes>. When reducing, data in the reduced part
2673 ("resize2fs", (RErr, [Device "device"]), 106, [],
2674 [], (* lvresize tests this *)
2675 "resize an ext2, ext3 or ext4 filesystem",
2677 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2678 the underlying device.
2680 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2681 on the C<device> before calling this command. For unknown reasons
2682 C<resize2fs> sometimes gives an error about this and sometimes not.
2683 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2684 calling this function.");
2686 ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2687 [InitBasicFS, Always, TestOutputList (
2688 [["find"; "/"]], ["lost+found"]);
2689 InitBasicFS, Always, TestOutputList (
2693 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2694 InitBasicFS, Always, TestOutputList (
2695 [["mkdir_p"; "/a/b/c"];
2696 ["touch"; "/a/b/c/d"];
2697 ["find"; "/a/b/"]], ["c"; "c/d"])],
2698 "find all files and directories",
2700 This command lists out all files and directories, recursively,
2701 starting at C<directory>. It is essentially equivalent to
2702 running the shell command C<find directory -print> but some
2703 post-processing happens on the output, described below.
2705 This returns a list of strings I<without any prefix>. Thus
2706 if the directory structure was:
2712 then the returned list from C<guestfs_find> C</tmp> would be
2720 If C<directory> is not a directory, then this command returns
2723 The returned list is sorted.
2725 See also C<guestfs_find0>.");
2727 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2728 [], (* lvresize tests this *)
2729 "check an ext2/ext3 filesystem",
2731 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2732 filesystem checker on C<device>, noninteractively (C<-p>),
2733 even if the filesystem appears to be clean (C<-f>).
2735 This command is only needed because of C<guestfs_resize2fs>
2736 (q.v.). Normally you should use C<guestfs_fsck>.");
2738 ("sleep", (RErr, [Int "secs"]), 109, [],
2739 [InitNone, Always, TestRun (
2741 "sleep for some seconds",
2743 Sleep for C<secs> seconds.");
2745 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2746 [InitNone, Always, TestOutputInt (
2747 [["part_disk"; "/dev/sda"; "mbr"];
2748 ["mkfs"; "ntfs"; "/dev/sda1"];
2749 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2750 InitNone, Always, TestOutputInt (
2751 [["part_disk"; "/dev/sda"; "mbr"];
2752 ["mkfs"; "ext2"; "/dev/sda1"];
2753 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2754 "probe NTFS volume",
2756 This command runs the L<ntfs-3g.probe(8)> command which probes
2757 an NTFS C<device> for mountability. (Not all NTFS volumes can
2758 be mounted read-write, and some cannot be mounted at all).
2760 C<rw> is a boolean flag. Set it to true if you want to test
2761 if the volume can be mounted read-write. Set it to false if
2762 you want to test if the volume can be mounted read-only.
2764 The return value is an integer which C<0> if the operation
2765 would succeed, or some non-zero value documented in the
2766 L<ntfs-3g.probe(8)> manual page.");
2768 ("sh", (RString "output", [String "command"]), 111, [],
2769 [], (* XXX needs tests *)
2770 "run a command via the shell",
2772 This call runs a command from the guest filesystem via the
2775 This is like C<guestfs_command>, but passes the command to:
2777 /bin/sh -c \"command\"
2779 Depending on the guest's shell, this usually results in
2780 wildcards being expanded, shell expressions being interpolated
2783 All the provisos about C<guestfs_command> apply to this call.");
2785 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2786 [], (* XXX needs tests *)
2787 "run a command via the shell returning lines",
2789 This is the same as C<guestfs_sh>, but splits the result
2790 into a list of lines.
2792 See also: C<guestfs_command_lines>");
2794 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2795 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2796 * code in stubs.c, since all valid glob patterns must start with "/".
2797 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2799 [InitBasicFS, Always, TestOutputList (
2800 [["mkdir_p"; "/a/b/c"];
2801 ["touch"; "/a/b/c/d"];
2802 ["touch"; "/a/b/c/e"];
2803 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2804 InitBasicFS, Always, TestOutputList (
2805 [["mkdir_p"; "/a/b/c"];
2806 ["touch"; "/a/b/c/d"];
2807 ["touch"; "/a/b/c/e"];
2808 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809 InitBasicFS, Always, TestOutputList (
2810 [["mkdir_p"; "/a/b/c"];
2811 ["touch"; "/a/b/c/d"];
2812 ["touch"; "/a/b/c/e"];
2813 ["glob_expand"; "/a/*/x/*"]], [])],
2814 "expand a wildcard path",
2816 This command searches for all the pathnames matching
2817 C<pattern> according to the wildcard expansion rules
2820 If no paths match, then this returns an empty list
2821 (note: not an error).
2823 It is just a wrapper around the C L<glob(3)> function
2824 with flags C<GLOB_MARK|GLOB_BRACE>.
2825 See that manual page for more details.");
2827 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2828 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2829 [["scrub_device"; "/dev/sdc"]])],
2830 "scrub (securely wipe) a device",
2832 This command writes patterns over C<device> to make data retrieval
2835 It is an interface to the L<scrub(1)> program. See that
2836 manual page for more details.");
2838 ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2839 [InitBasicFS, Always, TestRun (
2840 [["write"; "/file"; "content"];
2841 ["scrub_file"; "/file"]])],
2842 "scrub (securely wipe) a file",
2844 This command writes patterns over a file to make data retrieval
2847 The file is I<removed> after scrubbing.
2849 It is an interface to the L<scrub(1)> program. See that
2850 manual page for more details.");
2852 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2853 [], (* XXX needs testing *)
2854 "scrub (securely wipe) free space",
2856 This command creates the directory C<dir> and then fills it
2857 with files until the filesystem is full, and scrubs the files
2858 as for C<guestfs_scrub_file>, and deletes them.
2859 The intention is to scrub any free space on the partition
2862 It is an interface to the L<scrub(1)> program. See that
2863 manual page for more details.");
2865 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2866 [InitBasicFS, Always, TestRun (
2868 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2869 "create a temporary directory",
2871 This command creates a temporary directory. The
2872 C<template> parameter should be a full pathname for the
2873 temporary directory name with the final six characters being
2876 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2877 the second one being suitable for Windows filesystems.
2879 The name of the temporary directory that was created
2882 The temporary directory is created with mode 0700
2883 and is owned by root.
2885 The caller is responsible for deleting the temporary
2886 directory and its contents after use.
2888 See also: L<mkdtemp(3)>");
2890 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2891 [InitISOFS, Always, TestOutputInt (
2892 [["wc_l"; "/10klines"]], 10000);
2893 (* Test for RHBZ#579608, absolute symbolic links. *)
2894 InitISOFS, Always, TestOutputInt (
2895 [["wc_l"; "/abssymlink"]], 10000)],
2896 "count lines in a file",
2898 This command counts the lines in a file, using the
2899 C<wc -l> external command.");
2901 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2902 [InitISOFS, Always, TestOutputInt (
2903 [["wc_w"; "/10klines"]], 10000)],
2904 "count words in a file",
2906 This command counts the words in a file, using the
2907 C<wc -w> external command.");
2909 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2910 [InitISOFS, Always, TestOutputInt (
2911 [["wc_c"; "/100kallspaces"]], 102400)],
2912 "count characters in a file",
2914 This command counts the characters in a file, using the
2915 C<wc -c> external command.");
2917 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2918 [InitISOFS, Always, TestOutputList (
2919 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2920 (* Test for RHBZ#579608, absolute symbolic links. *)
2921 InitISOFS, Always, TestOutputList (
2922 [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2923 "return first 10 lines of a file",
2925 This command returns up to the first 10 lines of a file as
2926 a list of strings.");
2928 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2929 [InitISOFS, Always, TestOutputList (
2930 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2931 InitISOFS, Always, TestOutputList (
2932 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933 InitISOFS, Always, TestOutputList (
2934 [["head_n"; "0"; "/10klines"]], [])],
2935 "return first N lines of a file",
2937 If the parameter C<nrlines> is a positive number, this returns the first
2938 C<nrlines> lines of the file C<path>.
2940 If the parameter C<nrlines> is a negative number, this returns lines
2941 from the file C<path>, excluding the last C<nrlines> lines.
2943 If the parameter C<nrlines> is zero, this returns an empty list.");
2945 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2946 [InitISOFS, Always, TestOutputList (
2947 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2948 "return last 10 lines of a file",
2950 This command returns up to the last 10 lines of a file as
2951 a list of strings.");
2953 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2954 [InitISOFS, Always, TestOutputList (
2955 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2956 InitISOFS, Always, TestOutputList (
2957 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958 InitISOFS, Always, TestOutputList (
2959 [["tail_n"; "0"; "/10klines"]], [])],
2960 "return last N lines of a file",
2962 If the parameter C<nrlines> is a positive number, this returns the last
2963 C<nrlines> lines of the file C<path>.
2965 If the parameter C<nrlines> is a negative number, this returns lines
2966 from the file C<path>, starting with the C<-nrlines>th line.
2968 If the parameter C<nrlines> is zero, this returns an empty list.");
2970 ("df", (RString "output", []), 125, [],
2971 [], (* XXX Tricky to test because it depends on the exact format
2972 * of the 'df' command and other imponderables.
2974 "report file system disk space usage",
2976 This command runs the C<df> command to report disk space used.
2978 This command is mostly useful for interactive sessions. It
2979 is I<not> intended that you try to parse the output string.
2980 Use C<statvfs> from programs.");
2982 ("df_h", (RString "output", []), 126, [],
2983 [], (* XXX Tricky to test because it depends on the exact format
2984 * of the 'df' command and other imponderables.
2986 "report file system disk space usage (human readable)",
2988 This command runs the C<df -h> command to report disk space used
2989 in human-readable format.
2991 This command is mostly useful for interactive sessions. It
2992 is I<not> intended that you try to parse the output string.
2993 Use C<statvfs> from programs.");
2995 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2996 [InitISOFS, Always, TestOutputInt (
2997 [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2998 "estimate file space usage",
3000 This command runs the C<du -s> command to estimate file space
3003 C<path> can be a file or a directory. If C<path> is a directory
3004 then the estimate includes the contents of the directory and all
3005 subdirectories (recursively).
3007 The result is the estimated size in I<kilobytes>
3008 (ie. units of 1024 bytes).");
3010 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3011 [InitISOFS, Always, TestOutputList (
3012 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3013 "list files in an initrd",
3015 This command lists out files contained in an initrd.
3017 The files are listed without any initial C</> character. The
3018 files are listed in the order they appear (not necessarily
3019 alphabetical). Directory names are listed as separate items.
3021 Old Linux kernels (2.4 and earlier) used a compressed ext2
3022 filesystem as initrd. We I<only> support the newer initramfs
3023 format (compressed cpio files).");
3025 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3027 "mount a file using the loop device",
3029 This command lets you mount C<file> (a filesystem image
3030 in a file) on a mount point. It is entirely equivalent to
3031 the command C<mount -o loop file mountpoint>.");
3033 ("mkswap", (RErr, [Device "device"]), 130, [],
3034 [InitEmpty, Always, TestRun (
3035 [["part_disk"; "/dev/sda"; "mbr"];
3036 ["mkswap"; "/dev/sda1"]])],
3037 "create a swap partition",
3039 Create a swap partition on C<device>.");
3041 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3042 [InitEmpty, Always, TestRun (
3043 [["part_disk"; "/dev/sda"; "mbr"];
3044 ["mkswap_L"; "hello"; "/dev/sda1"]])],
3045 "create a swap partition with a label",
3047 Create a swap partition on C<device> with label C<label>.
3049 Note that you cannot attach a swap label to a block device
3050 (eg. C</dev/sda>), just to a partition. This appears to be
3051 a limitation of the kernel or swap tools.");
3053 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3054 (let uuid = uuidgen () in
3055 [InitEmpty, Always, TestRun (
3056 [["part_disk"; "/dev/sda"; "mbr"];
3057 ["mkswap_U"; uuid; "/dev/sda1"]])]),
3058 "create a swap partition with an explicit UUID",
3060 Create a swap partition on C<device> with UUID C<uuid>.");
3062 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3063 [InitBasicFS, Always, TestOutputStruct (
3064 [["mknod"; "0o10777"; "0"; "0"; "/node"];
3065 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3066 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3067 InitBasicFS, Always, TestOutputStruct (
3068 [["mknod"; "0o60777"; "66"; "99"; "/node"];
3069 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3070 "make block, character or FIFO devices",
3072 This call creates block or character special devices, or
3073 named pipes (FIFOs).
3075 The C<mode> parameter should be the mode, using the standard
3076 constants. C<devmajor> and C<devminor> are the
3077 device major and minor numbers, only used when creating block
3078 and character special devices.
3080 Note that, just like L<mknod(2)>, the mode must be bitwise
3081 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3082 just creates a regular file). These constants are
3083 available in the standard Linux header files, or you can use
3084 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3085 which are wrappers around this command which bitwise OR
3086 in the appropriate constant for you.
3088 The mode actually set is affected by the umask.");
3090 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3091 [InitBasicFS, Always, TestOutputStruct (
3092 [["mkfifo"; "0o777"; "/node"];
3093 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3094 "make FIFO (named pipe)",
3096 This call creates a FIFO (named pipe) called C<path> with
3097 mode C<mode>. It is just a convenient wrapper around
3100 The mode actually set is affected by the umask.");
3102 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3103 [InitBasicFS, Always, TestOutputStruct (
3104 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3105 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3106 "make block device node",
3108 This call creates a block device node called C<path> with
3109 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3110 It is just a convenient wrapper around C<guestfs_mknod>.
3112 The mode actually set is affected by the umask.");
3114 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3115 [InitBasicFS, Always, TestOutputStruct (
3116 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3117 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3118 "make char device node",
3120 This call creates a char device node called C<path> with
3121 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3122 It is just a convenient wrapper around C<guestfs_mknod>.
3124 The mode actually set is affected by the umask.");
3126 ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3127 [InitEmpty, Always, TestOutputInt (
3128 [["umask"; "0o22"]], 0o22)],
3129 "set file mode creation mask (umask)",
3131 This function sets the mask used for creating new files and
3132 device nodes to C<mask & 0777>.
3134 Typical umask values would be C<022> which creates new files
3135 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3136 C<002> which creates new files with permissions like
3137 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3139 The default umask is C<022>. This is important because it
3140 means that directories and device nodes will be created with
3141 C<0644> or C<0755> mode even if you specify C<0777>.
3143 See also C<guestfs_get_umask>,
3144 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3146 This call returns the previous umask.");
3148 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3150 "read directories entries",
3152 This returns the list of directory entries in directory C<dir>.
3154 All entries in the directory are returned, including C<.> and
3155 C<..>. The entries are I<not> sorted, but returned in the same
3156 order as the underlying filesystem.
3158 Also this call returns basic file type information about each
3159 file. The C<ftyp> field will contain one of the following characters:
3197 The L<readdir(3)> call returned a C<d_type> field with an
3202 This function is primarily intended for use by programs. To
3203 get a simple list of names, use C<guestfs_ls>. To get a printable
3204 directory for human consumption, use C<guestfs_ll>.");
3206 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3208 "create partitions on a block device",
3210 This is a simplified interface to the C<guestfs_sfdisk>
3211 command, where partition sizes are specified in megabytes
3212 only (rounded to the nearest cylinder) and you don't need
3213 to specify the cyls, heads and sectors parameters which
3214 were rarely if ever used anyway.
3216 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3217 and C<guestfs_part_disk>");
3219 ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3221 "determine file type inside a compressed file",
3223 This command runs C<file> after first decompressing C<path>
3226 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3228 Since 1.0.63, use C<guestfs_file> instead which can now
3229 process compressed files.");
3231 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3233 "list extended attributes of a file or directory",
3235 This call lists the extended attributes of the file or directory
3238 At the system call level, this is a combination of the
3239 L<listxattr(2)> and L<getxattr(2)> calls.
3241 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3243 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3245 "list extended attributes of a file or directory",
3247 This is the same as C<guestfs_getxattrs>, but if C<path>
3248 is a symbolic link, then it returns the extended attributes
3249 of the link itself.");
3251 ("setxattr", (RErr, [String "xattr";
3252 String "val"; Int "vallen"; (* will be BufferIn *)
3253 Pathname "path"]), 143, [Optional "linuxxattrs"],
3255 "set extended attribute of a file or directory",
3257 This call sets the extended attribute named C<xattr>
3258 of the file C<path> to the value C<val> (of length C<vallen>).
3259 The value is arbitrary 8 bit data.
3261 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3263 ("lsetxattr", (RErr, [String "xattr";
3264 String "val"; Int "vallen"; (* will be BufferIn *)
3265 Pathname "path"]), 144, [Optional "linuxxattrs"],
3267 "set extended attribute of a file or directory",
3269 This is the same as C<guestfs_setxattr>, but if C<path>
3270 is a symbolic link, then it sets an extended attribute
3271 of the link itself.");
3273 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3275 "remove extended attribute of a file or directory",
3277 This call removes the extended attribute named C<xattr>
3278 of the file C<path>.
3280 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3282 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3284 "remove extended attribute of a file or directory",
3286 This is the same as C<guestfs_removexattr>, but if C<path>
3287 is a symbolic link, then it removes an extended attribute
3288 of the link itself.");
3290 ("mountpoints", (RHashtable "mps", []), 147, [],
3294 This call is similar to C<guestfs_mounts>. That call returns
3295 a list of devices. This one returns a hash table (map) of
3296 device name to directory where the device is mounted.");
3298 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3299 (* This is a special case: while you would expect a parameter
3300 * of type "Pathname", that doesn't work, because it implies
3301 * NEED_ROOT in the generated calling code in stubs.c, and
3302 * this function cannot use NEED_ROOT.
3305 "create a mountpoint",
3307 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3308 specialized calls that can be used to create extra mountpoints
3309 before mounting the first filesystem.
3311 These calls are I<only> necessary in some very limited circumstances,
3312 mainly the case where you want to mount a mix of unrelated and/or
3313 read-only filesystems together.
3315 For example, live CDs often contain a \"Russian doll\" nest of
3316 filesystems, an ISO outer layer, with a squashfs image inside, with
3317 an ext2/3 image inside that. You can unpack this as follows
3320 add-ro Fedora-11-i686-Live.iso
3323 mkmountpoint /squash
3326 mount-loop /cd/LiveOS/squashfs.img /squash
3327 mount-loop /squash/LiveOS/ext3fs.img /ext3
3329 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3331 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3333 "remove a mountpoint",
3335 This calls removes a mountpoint that was previously created
3336 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3337 for full details.");
3339 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3340 [InitISOFS, Always, TestOutputBuffer (
3341 [["read_file"; "/known-4"]], "abc\ndef\nghi");
3342 (* Test various near large, large and too large files (RHBZ#589039). *)
3343 InitBasicFS, Always, TestLastFail (
3345 ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3346 ["read_file"; "/a"]]);
3347 InitBasicFS, Always, TestLastFail (
3349 ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3350 ["read_file"; "/a"]]);
3351 InitBasicFS, Always, TestLastFail (
3353 ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3354 ["read_file"; "/a"]])],
3357 This calls returns the contents of the file C<path> as a
3360 Unlike C<guestfs_cat>, this function can correctly
3361 handle files that contain embedded ASCII NUL characters.
3362 However unlike C<guestfs_download>, this function is limited
3363 in the total size of file that can be handled.");
3365 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3366 [InitISOFS, Always, TestOutputList (
3367 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3368 InitISOFS, Always, TestOutputList (
3369 [["grep"; "nomatch"; "/test-grep.txt"]], []);
3370 (* Test for RHBZ#579608, absolute symbolic links. *)
3371 InitISOFS, Always, TestOutputList (
3372 [["grep"; "nomatch"; "/abssymlink"]], [])],
3373 "return lines matching a pattern",
3375 This calls the external C<grep> program and returns the
3378 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3379 [InitISOFS, Always, TestOutputList (
3380 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3381 "return lines matching a pattern",
3383 This calls the external C<egrep> program and returns the
3386 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3387 [InitISOFS, Always, TestOutputList (
3388 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389 "return lines matching a pattern",
3391 This calls the external C<fgrep> program and returns the
3394 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3395 [InitISOFS, Always, TestOutputList (
3396 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3397 "return lines matching a pattern",
3399 This calls the external C<grep -i> program and returns the
3402 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3403 [InitISOFS, Always, TestOutputList (
3404 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405 "return lines matching a pattern",
3407 This calls the external C<egrep -i> program and returns the
3410 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3411 [InitISOFS, Always, TestOutputList (
3412 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413 "return lines matching a pattern",
3415 This calls the external C<fgrep -i> program and returns the
3418 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3419 [InitISOFS, Always, TestOutputList (
3420 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3421 "return lines matching a pattern",
3423 This calls the external C<zgrep> program and returns the
3426 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3427 [InitISOFS, Always, TestOutputList (
3428 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429 "return lines matching a pattern",
3431 This calls the external C<zegrep> program and returns the
3434 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3435 [InitISOFS, Always, TestOutputList (
3436 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437 "return lines matching a pattern",
3439 This calls the external C<zfgrep> program and returns the
3442 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3443 [InitISOFS, Always, TestOutputList (
3444 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3445 "return lines matching a pattern",
3447 This calls the external C<zgrep -i> program and returns the
3450 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3451 [InitISOFS, Always, TestOutputList (
3452 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453 "return lines matching a pattern",
3455 This calls the external C<zegrep -i> program and returns the
3458 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3459 [InitISOFS, Always, TestOutputList (
3460 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461 "return lines matching a pattern",
3463 This calls the external C<zfgrep -i> program and returns the
3466 ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3467 [InitISOFS, Always, TestOutput (
3468 [["realpath"; "/../directory"]], "/directory")],
3469 "canonicalized absolute pathname",
3471 Return the canonicalized absolute pathname of C<path>. The
3472 returned path has no C<.>, C<..> or symbolic link path elements.");
3474 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3475 [InitBasicFS, Always, TestOutputStruct (
3478 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3479 "create a hard link",
3481 This command creates a hard link using the C<ln> command.");
3483 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3484 [InitBasicFS, Always, TestOutputStruct (
3487 ["ln_f"; "/a"; "/b"];
3488 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3489 "create a hard link",
3491 This command creates a hard link using the C<ln -f> command.
3492 The C<-f> option removes the link (C<linkname>) if it exists already.");
3494 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3495 [InitBasicFS, Always, TestOutputStruct (
3497 ["ln_s"; "a"; "/b"];
3498 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3499 "create a symbolic link",
3501 This command creates a symbolic link using the C<ln -s> command.");
3503 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3504 [InitBasicFS, Always, TestOutput (
3505 [["mkdir_p"; "/a/b"];
3506 ["touch"; "/a/b/c"];
3507 ["ln_sf"; "../d"; "/a/b/c"];
3508 ["readlink"; "/a/b/c"]], "../d")],
3509 "create a symbolic link",
3511 This command creates a symbolic link using the C<ln -sf> command,
3512 The C<-f> option removes the link (C<linkname>) if it exists already.");
3514 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3515 [] (* XXX tested above *),
3516 "read the target of a symbolic link",
3518 This command reads the target of a symbolic link.");
3520 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3521 [InitBasicFS, Always, TestOutputStruct (
3522 [["fallocate"; "/a"; "1000000"];
3523 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3524 "preallocate a file in the guest filesystem",
3526 This command preallocates a file (containing zero bytes) named
3527 C<path> of size C<len> bytes. If the file exists already, it
3530 Do not confuse this with the guestfish-specific
3531 C<alloc> command which allocates a file in the host and
3532 attaches it as a device.");
3534 ("swapon_device", (RErr, [Device "device"]), 170, [],
3535 [InitPartition, Always, TestRun (
3536 [["mkswap"; "/dev/sda1"];
3537 ["swapon_device"; "/dev/sda1"];
3538 ["swapoff_device"; "/dev/sda1"]])],
3539 "enable swap on device",
3541 This command enables the libguestfs appliance to use the
3542 swap device or partition named C<device>. The increased
3543 memory is made available for all commands, for example
3544 those run using C<guestfs_command> or C<guestfs_sh>.
3546 Note that you should not swap to existing guest swap
3547 partitions unless you know what you are doing. They may
3548 contain hibernation information, or other information that
3549 the guest doesn't want you to trash. You also risk leaking
3550 information about the host to the guest this way. Instead,
3551 attach a new host device to the guest and swap on that.");
3553 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3554 [], (* XXX tested by swapon_device *)
3555 "disable swap on device",
3557 This command disables the libguestfs appliance swap
3558 device or partition named C<device>.
3559 See C<guestfs_swapon_device>.");
3561 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3562 [InitBasicFS, Always, TestRun (
3563 [["fallocate"; "/swap"; "8388608"];
3564 ["mkswap_file"; "/swap"];
3565 ["swapon_file"; "/swap"];
3566 ["swapoff_file"; "/swap"]])],
3567 "enable swap on file",
3569 This command enables swap to a file.
3570 See C<guestfs_swapon_device> for other notes.");
3572 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3573 [], (* XXX tested by swapon_file *)
3574 "disable swap on file",
3576 This command disables the libguestfs appliance swap on file.");
3578 ("swapon_label", (RErr, [String "label"]), 174, [],
3579 [InitEmpty, Always, TestRun (
3580 [["part_disk"; "/dev/sdb"; "mbr"];
3581 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3582 ["swapon_label"; "swapit"];
3583 ["swapoff_label"; "swapit"];
3584 ["zero"; "/dev/sdb"];
3585 ["blockdev_rereadpt"; "/dev/sdb"]])],
3586 "enable swap on labeled swap partition",
3588 This command enables swap to a labeled swap partition.
3589 See C<guestfs_swapon_device> for other notes.");
3591 ("swapoff_label", (RErr, [String "label"]), 175, [],
3592 [], (* XXX tested by swapon_label *)
3593 "disable swap on labeled swap partition",
3595 This command disables the libguestfs appliance swap on
3596 labeled swap partition.");
3598 ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3599 (let uuid = uuidgen () in
3600 [InitEmpty, Always, TestRun (
3601 [["mkswap_U"; uuid; "/dev/sdb"];
3602 ["swapon_uuid"; uuid];
3603 ["swapoff_uuid"; uuid]])]),
3604 "enable swap on swap partition by UUID",
3606 This command enables swap to a swap partition with the given UUID.
3607 See C<guestfs_swapon_device> for other notes.");
3609 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3610 [], (* XXX tested by swapon_uuid *)
3611 "disable swap on swap partition by UUID",
3613 This command disables the libguestfs appliance swap partition
3614 with the given UUID.");
3616 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3617 [InitBasicFS, Always, TestRun (
3618 [["fallocate"; "/swap"; "8388608"];
3619 ["mkswap_file"; "/swap"]])],
3620 "create a swap file",
3624 This command just writes a swap file signature to an existing
3625 file. To create the file itself, use something like C<guestfs_fallocate>.");
3627 ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3628 [InitISOFS, Always, TestRun (
3629 [["inotify_init"; "0"]])],
3630 "create an inotify handle",
3632 This command creates a new inotify handle.
3633 The inotify subsystem can be used to notify events which happen to
3634 objects in the guest filesystem.
3636 C<maxevents> is the maximum number of events which will be
3637 queued up between calls to C<guestfs_inotify_read> or
3638 C<guestfs_inotify_files>.
3639 If this is passed as C<0>, then the kernel (or previously set)
3640 default is used. For Linux 2.6.29 the default was 16384 events.
3641 Beyond this limit, the kernel throws away events, but records
3642 the fact that it threw them away by setting a flag
3643 C<IN_Q_OVERFLOW> in the returned structure list (see
3644 C<guestfs_inotify_read>).
3646 Before any events are generated, you have to add some
3647 watches to the internal watch list. See:
3648 C<guestfs_inotify_add_watch>,
3649 C<guestfs_inotify_rm_watch> and
3650 C<guestfs_inotify_watch_all>.
3652 Queued up events should be read periodically by calling
3653 C<guestfs_inotify_read>
3654 (or C<guestfs_inotify_files> which is just a helpful
3655 wrapper around C<guestfs_inotify_read>). If you don't
3656 read the events out often enough then you risk the internal
3659 The handle should be closed after use by calling
3660 C<guestfs_inotify_close>. This also removes any
3661 watches automatically.
3663 See also L<inotify(7)> for an overview of the inotify interface
3664 as exposed by the Linux kernel, which is roughly what we expose
3665 via libguestfs. Note that there is one global inotify handle
3666 per libguestfs instance.");
3668 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3669 [InitBasicFS, Always, TestOutputList (
3670 [["inotify_init"; "0"];
3671 ["inotify_add_watch"; "/"; "1073741823"];
3674 ["inotify_files"]], ["a"; "b"])],
3675 "add an inotify watch",
3677 Watch C<path> for the events listed in C<mask>.
3679 Note that if C<path> is a directory then events within that
3680 directory are watched, but this does I<not> happen recursively
3681 (in subdirectories).
3683 Note for non-C or non-Linux callers: the inotify events are
3684 defined by the Linux kernel ABI and are listed in
3685 C</usr/include/sys/inotify.h>.");
3687 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3689 "remove an inotify watch",
3691 Remove a previously defined inotify watch.
3692 See C<guestfs_inotify_add_watch>.");
3694 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3696 "return list of inotify events",
3698 Return the complete queue of events that have happened
3699 since the previous read call.
3701 If no events have happened, this returns an empty list.
3703 I<Note>: In order to make sure that all events have been
3704 read, you must call this function repeatedly until it
3705 returns an empty list. The reason is that the call will
3706 read events up to the maximum appliance-to-host message
3707 size and leave remaining events in the queue.");
3709 ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3711 "return list of watched files that had events",
3713 This function is a helpful wrapper around C<guestfs_inotify_read>
3714 which just returns a list of pathnames of objects that were
3715 touched. The returned pathnames are sorted and deduplicated.");
3717 ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3719 "close the inotify handle",
3721 This closes the inotify handle which was previously
3722 opened by inotify_init. It removes all watches, throws
3723 away any pending events, and deallocates all resources.");
3725 ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3727 "set SELinux security context",
3729 This sets the SELinux security context of the daemon
3730 to the string C<context>.
3732 See the documentation about SELINUX in L<guestfs(3)>.");
3734 ("getcon", (RString "context", []), 186, [Optional "selinux"],
3736 "get SELinux security context",
3738 This gets the SELinux security context of the daemon.
3740 See the documentation about SELINUX in L<guestfs(3)>,
3741 and C<guestfs_setcon>");
3743 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3744 [InitEmpty, Always, TestOutput (
3745 [["part_disk"; "/dev/sda"; "mbr"];
3746 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3747 ["mount_options"; ""; "/dev/sda1"; "/"];
3748 ["write"; "/new"; "new file contents"];
3749 ["cat"; "/new"]], "new file contents");
3750 InitEmpty, Always, TestRun (
3751 [["part_disk"; "/dev/sda"; "mbr"];
3752 ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3753 InitEmpty, Always, TestLastFail (
3754 [["part_disk"; "/dev/sda"; "mbr"];
3755 ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3756 InitEmpty, Always, TestLastFail (
3757 [["part_disk"; "/dev/sda"; "mbr"];
3758 ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3759 InitEmpty, IfAvailable "ntfsprogs", TestRun (
3760 [["part_disk"; "/dev/sda"; "mbr"];
3761 ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3762 "make a filesystem with block size",
3764 This call is similar to C<guestfs_mkfs>, but it allows you to
3765 control the block size of the resulting filesystem. Supported
3766 block sizes depend on the filesystem type, but typically they
3767 are C<1024>, C<2048> or C<4096> only.
3769 For VFAT and NTFS the C<blocksize> parameter is treated as
3770 the requested cluster size.");
3772 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3773 [InitEmpty, Always, TestOutput (
3774 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3775 ["mke2journal"; "4096"; "/dev/sda1"];
3776 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3777 ["mount_options"; ""; "/dev/sda2"; "/"];
3778 ["write"; "/new"; "new file contents"];
3779 ["cat"; "/new"]], "new file contents")],
3780 "make ext2/3/4 external journal",
3782 This creates an ext2 external journal on C<device>. It is equivalent
3785 mke2fs -O journal_dev -b blocksize device");
3787 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3788 [InitEmpty, Always, TestOutput (
3789 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3790 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3791 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3792 ["mount_options"; ""; "/dev/sda2"; "/"];
3793 ["write"; "/new"; "new file contents"];
3794 ["cat"; "/new"]], "new file contents")],
3795 "make ext2/3/4 external journal with label",
3797 This creates an ext2 external journal on C<device> with label C<label>.");
3799 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3800 (let uuid = uuidgen () in
3801 [InitEmpty, Always, TestOutput (
3802 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3803 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3804 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3805 ["mount_options"; ""; "/dev/sda2"; "/"];
3806 ["write"; "/new"; "new file contents"];
3807 ["cat"; "/new"]], "new file contents")]),
3808 "make ext2/3/4 external journal with UUID",
3810 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3812 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3814 "make ext2/3/4 filesystem with external journal",
3816 This creates an ext2/3/4 filesystem on C<device> with
3817 an external journal on C<journal>. It is equivalent
3820 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3822 See also C<guestfs_mke2journal>.");
3824 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3826 "make ext2/3/4 filesystem with external journal",
3828 This creates an ext2/3/4 filesystem on C<device> with
3829 an external journal on the journal labeled C<label>.
3831 See also C<guestfs_mke2journal_L>.");
3833 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3835 "make ext2/3/4 filesystem with external journal",
3837 This creates an ext2/3/4 filesystem on C<device> with
3838 an external journal on the journal with UUID C<uuid>.
3840 See also C<guestfs_mke2journal_U>.");
3842 ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3843 [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3844 "load a kernel module",
3846 This loads a kernel module in the appliance.
3848 The kernel module must have been whitelisted when libguestfs
3849 was built (see C<appliance/kmod.whitelist.in> in the source).");
3851 ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3852 [InitNone, Always, TestOutput (
3853 [["echo_daemon"; "This is a test"]], "This is a test"
3855 "echo arguments back to the client",
3857 This command concatenates the list of C<words> passed with single spaces
3858 between them and returns the resulting string.
3860 You can use this command to test the connection through to the daemon.
3862 See also C<guestfs_ping_daemon>.");
3864 ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3865 [], (* There is a regression test for this. *)
3866 "find all files and directories, returning NUL-separated list",
3868 This command lists out all files and directories, recursively,
3869 starting at C<directory>, placing the resulting list in the
3870 external file called C<files>.
3872 This command works the same way as C<guestfs_find> with the
3873 following exceptions:
3879 The resulting list is written to an external file.
3883 Items (filenames) in the result are separated
3884 by C<\\0> characters. See L<find(1)> option I<-print0>.
3888 This command is not limited in the number of names that it
3893 The result list is not sorted.
3897 ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3898 [InitISOFS, Always, TestOutput (
3899 [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3900 InitISOFS, Always, TestOutput (
3901 [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3902 InitISOFS, Always, TestOutput (
3903 [["case_sensitive_path"; "/Known-1"]], "/known-1");
3904 InitISOFS, Always, TestLastFail (
3905 [["case_sensitive_path"; "/Known-1/"]]);
3906 InitBasicFS, Always, TestOutput (
3908 ["mkdir"; "/a/bbb"];
3909 ["touch"; "/a/bbb/c"];
3910 ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3911 InitBasicFS, Always, TestOutput (
3913 ["mkdir"; "/a/bbb"];
3914 ["touch"; "/a/bbb/c"];
3915 ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3916 InitBasicFS, Always, TestLastFail (
3918 ["mkdir"; "/a/bbb"];
3919 ["touch"; "/a/bbb/c"];
3920 ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3921 "return true path on case-insensitive filesystem",
3923 This can be used to resolve case insensitive paths on
3924 a filesystem which is case sensitive. The use case is
3925 to resolve paths which you have read from Windows configuration
3926 files or the Windows Registry, to the true path.
3928 The command handles a peculiarity of the Linux ntfs-3g
3929 filesystem driver (and probably others), which is that although
3930 the underlying filesystem is case-insensitive, the driver
3931 exports the filesystem to Linux as case-sensitive.
3933 One consequence of this is that special directories such
3934 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3935 (or other things) depending on the precise details of how
3936 they were created. In Windows itself this would not be
3939 Bug or feature? You decide:
3940 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3942 This function resolves the true case of each element in the
3943 path and returns the case-sensitive path.
3945 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3946 might return C<\"/WINDOWS/system32\"> (the exact return value
3947 would depend on details of how the directories were originally
3948 created under Windows).
3951 This function does not handle drive names, backslashes etc.
3953 See also C<guestfs_realpath>.");
3955 ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3956 [InitBasicFS, Always, TestOutput (
3957 [["vfs_type"; "/dev/sda1"]], "ext2")],
3958 "get the Linux VFS type corresponding to a mounted device",
3960 This command gets the filesystem type corresponding to
3961 the filesystem on C<device>.
3963 For most filesystems, the result is the name of the Linux
3964 VFS module which would be used to mount this filesystem
3965 if you mounted it without specifying the filesystem type.
3966 For example a string such as C<ext3> or C<ntfs>.");
3968 ("truncate", (RErr, [Pathname "path"]), 199, [],
3969 [InitBasicFS, Always, TestOutputStruct (
3970 [["write"; "/test"; "some stuff so size is not zero"];
3971 ["truncate"; "/test"];
3972 ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3973 "truncate a file to zero size",
3975 This command truncates C<path> to a zero-length file. The
3976 file must exist already.");
3978 ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3979 [InitBasicFS, Always, TestOutputStruct (
3980 [["touch"; "/test"];
3981 ["truncate_size"; "/test"; "1000"];
3982 ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3983 "truncate a file to a particular size",
3985 This command truncates C<path> to size C<size> bytes. The file
3988 If the current file size is less than C<size> then
3989 the file is extended to the required size with zero bytes.
3990 This creates a sparse file (ie. disk blocks are not allocated
3991 for the file until you write to it). To create a non-sparse
3992 file of zeroes, use C<guestfs_fallocate64> instead.");
3994 ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3995 [InitBasicFS, Always, TestOutputStruct (
3996 [["touch"; "/test"];
3997 ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3998 ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3999 "set timestamp of a file with nanosecond precision",
4001 This command sets the timestamps of a file with nanosecond
4004 C<atsecs, atnsecs> are the last access time (atime) in secs and
4005 nanoseconds from the epoch.
4007 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4008 secs and nanoseconds from the epoch.
4010 If the C<*nsecs> field contains the special value C<-1> then
4011 the corresponding timestamp is set to the current time. (The
4012 C<*secs> field is ignored in this case).
4014 If the C<*nsecs> field contains the special value C<-2> then
4015 the corresponding timestamp is left unchanged. (The
4016 C<*secs> field is ignored in this case).");
4018 ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4019 [InitBasicFS, Always, TestOutputStruct (
4020 [["mkdir_mode"; "/test"; "0o111"];
4021 ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4022 "create a directory with a particular mode",
4024 This command creates a directory, setting the initial permissions
4025 of the directory to C<mode>.
4027 For common Linux filesystems, the actual mode which is set will
4028 be C<mode & ~umask & 01777>. Non-native-Linux filesystems may
4029 interpret the mode in other ways.
4031 See also C<guestfs_mkdir>, C<guestfs_umask>");
4033 ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4035 "change file owner and group",
4037 Change the file owner to C<owner> and group to C<group>.
4038 This is like C<guestfs_chown> but if C<path> is a symlink then
4039 the link itself is changed, not the target.
4041 Only numeric uid and gid are supported. If you want to use
4042 names, you will need to locate and parse the password file
4043 yourself (Augeas support makes this relatively easy).");
4045 ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4047 "lstat on multiple files",
4049 This call allows you to perform the C<guestfs_lstat> operation
4050 on multiple files, where all files are in the directory C<path>.
4051 C<names> is the list of files from this directory.
4053 On return you get a list of stat structs, with a one-to-one
4054 correspondence to the C<names> list. If any name did not exist
4055 or could not be lstat'd, then the C<ino> field of that structure
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 See also C<guestfs_lxattrlist> for a similarly efficient call
4061 for getting extended attributes. Very long directory listings
4062 might cause the protocol message size to be exceeded, causing
4063 this call to fail. The caller must split up such requests
4064 into smaller groups of names.");
4066 ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4068 "lgetxattr on multiple files",
4070 This call allows you to get the extended attributes
4071 of multiple files, where all files are in the directory C<path>.
4072 C<names> is the list of files from this directory.
4074 On return you get a flat list of xattr structs which must be
4075 interpreted sequentially. The first xattr struct always has a zero-length
4076 C<attrname>. C<attrval> in this struct is zero-length
4077 to indicate there was an error doing C<lgetxattr> for this
4078 file, I<or> is a C string which is a decimal number
4079 (the number of following attributes for this file, which could
4080 be C<\"0\">). Then after the first xattr struct are the
4081 zero or more attributes for the first named file.
4082 This repeats for the second and subsequent files.
4084 This call is intended for programs that want to efficiently
4085 list a directory contents without making many round-trips.
4086 See also C<guestfs_lstatlist> for a similarly efficient call
4087 for getting standard stats. Very long directory listings
4088 might cause the protocol message size to be exceeded, causing
4089 this call to fail. The caller must split up such requests
4090 into smaller groups of names.");
4092 ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4094 "readlink on multiple files",
4096 This call allows you to do a C<readlink> operation
4097 on multiple files, where all files are in the directory C<path>.
4098 C<names> is the list of files from this directory.
4100 On return you get a list of strings, with a one-to-one
4101 correspondence to the C<names> list. Each string is the
4102 value of the symbolic link.
4104 If the C<readlink(2)> operation fails on any name, then
4105 the corresponding result string is the empty string C<\"\">.
4106 However the whole operation is completed even if there
4107 were C<readlink(2)> errors, and so you can call this
4108 function with names where you don't know if they are
4109 symbolic links already (albeit slightly less efficient).
4111 This call is intended for programs that want to efficiently
4112 list a directory contents without making many round-trips.
4113 Very long directory listings might cause the protocol
4114 message size to be exceeded, causing
4115 this call to fail. The caller must split up such requests
4116 into smaller groups of names.");
4118 ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4119 [InitISOFS, Always, TestOutputBuffer (
4120 [["pread"; "/known-4"; "1"; "3"]], "\n");
4121 InitISOFS, Always, TestOutputBuffer (
4122 [["pread"; "/empty"; "0"; "100"]], "")],
4123 "read part of a file",
4125 This command lets you read part of a file. It reads C<count>
4126 bytes of the file, starting at C<offset>, from file C<path>.
4128 This may read fewer bytes than requested. For further details
4129 see the L<pread(2)> system call.
4131 See also C<guestfs_pwrite>.");
4133 ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4134 [InitEmpty, Always, TestRun (
4135 [["part_init"; "/dev/sda"; "gpt"]])],
4136 "create an empty partition table",
4138 This creates an empty partition table on C<device> of one of the
4139 partition types listed below. Usually C<parttype> should be
4140 either C<msdos> or C<gpt> (for large disks).
4142 Initially there are no partitions. Following this, you should
4143 call C<guestfs_part_add> for each partition required.
4145 Possible values for C<parttype> are:
4149 =item B<efi> | B<gpt>
4151 Intel EFI / GPT partition table.
4153 This is recommended for >= 2 TB partitions that will be accessed
4154 from Linux and Intel-based Mac OS X. It also has limited backwards
4155 compatibility with the C<mbr> format.
4157 =item B<mbr> | B<msdos>
4159 The standard PC \"Master Boot Record\" (MBR) format used
4160 by MS-DOS and Windows. This partition type will B<only> work
4161 for device sizes up to 2 TB. For large disks we recommend
4166 Other partition table types that may work but are not
4175 =item B<amiga> | B<rdb>
4177 Amiga \"Rigid Disk Block\" format.
4185 DASD, used on IBM mainframes.
4193 Old Mac partition format. Modern Macs use C<gpt>.
4197 NEC PC-98 format, common in Japan apparently.
4205 ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4206 [InitEmpty, Always, TestRun (
4207 [["part_init"; "/dev/sda"; "mbr"];
4208 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4209 InitEmpty, Always, TestRun (
4210 [["part_init"; "/dev/sda"; "gpt"];
4211 ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4212 ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4213 InitEmpty, Always, TestRun (
4214 [["part_init"; "/dev/sda"; "mbr"];
4215 ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4216 ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4217 ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4218 ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4219 "add a partition to the device",
4221 This command adds a partition to C<device>. If there is no partition
4222 table on the device, call C<guestfs_part_init> first.
4224 The C<prlogex> parameter is the type of partition. Normally you
4225 should pass C<p> or C<primary> here, but MBR partition tables also
4226 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4229 C<startsect> and C<endsect> are the start and end of the partition
4230 in I<sectors>. C<endsect> may be negative, which means it counts
4231 backwards from the end of the disk (C<-1> is the last sector).
4233 Creating a partition which covers the whole disk is not so easy.
4234 Use C<guestfs_part_disk> to do that.");
4236 ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4237 [InitEmpty, Always, TestRun (
4238 [["part_disk"; "/dev/sda"; "mbr"]]);
4239 InitEmpty, Always, TestRun (
4240 [["part_disk"; "/dev/sda"; "gpt"]])],
4241 "partition whole disk with a single primary partition",
4243 This command is simply a combination of C<guestfs_part_init>
4244 followed by C<guestfs_part_add> to create a single primary partition
4245 covering the whole disk.
4247 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4248 but other possible values are described in C<guestfs_part_init>.");
4250 ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4251 [InitEmpty, Always, TestRun (
4252 [["part_disk"; "/dev/sda"; "mbr"];
4253 ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4254 "make a partition bootable",
4256 This sets the bootable flag on partition numbered C<partnum> on
4257 device C<device>. Note that partitions are numbered from 1.
4259 The bootable flag is used by some operating systems (notably
4260 Windows) to determine which partition to boot from. It is by
4261 no means universally recognized.");
4263 ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4264 [InitEmpty, Always, TestRun (
4265 [["part_disk"; "/dev/sda"; "gpt"];
4266 ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4267 "set partition name",
4269 This sets the partition name on partition numbered C<partnum> on
4270 device C<device>. Note that partitions are numbered from 1.
4272 The partition name can only be set on certain types of partition
4273 table. This works on C<gpt> but not on C<mbr> partitions.");
4275 ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4276 [], (* XXX Add a regression test for this. *)
4277 "list partitions on a device",
4279 This command parses the partition table on C<device> and
4280 returns the list of partitions found.
4282 The fields in the returned structure are:
4288 Partition number, counting from 1.
4292 Start of the partition I<in bytes>. To get sectors you have to
4293 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4297 End of the partition in bytes.
4301 Size of the partition in bytes.
4305 ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4306 [InitEmpty, Always, TestOutput (
4307 [["part_disk"; "/dev/sda"; "gpt"];
4308 ["part_get_parttype"; "/dev/sda"]], "gpt")],
4309 "get the partition table type",
4311 This command examines the partition table on C<device> and
4312 returns the partition table type (format) being used.
4314 Common return values include: C<msdos> (a DOS/Windows style MBR
4315 partition table), C<gpt> (a GPT/EFI-style partition table). Other
4316 values are possible, although unusual. See C<guestfs_part_init>
4319 ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4320 [InitBasicFS, Always, TestOutputBuffer (
4321 [["fill"; "0x63"; "10"; "/test"];
4322 ["read_file"; "/test"]], "cccccccccc")],
4323 "fill a file with octets",
4325 This command creates a new file called C<path>. The initial
4326 content of the file is C<len> octets of C<c>, where C<c>
4327 must be a number in the range C<[0..255]>.
4329 To fill a file with zero bytes (sparsely), it is
4330 much more efficient to use C<guestfs_truncate_size>.
4331 To create a file with a pattern of repeating bytes
4332 use C<guestfs_fill_pattern>.");
4334 ("available", (RErr, [StringList "groups"]), 216, [],
4335 [InitNone, Always, TestRun [["available"; ""]]],
4336 "test availability of some parts of the API",
4338 This command is used to check the availability of some
4339 groups of functionality in the appliance, which not all builds of
4340 the libguestfs appliance will be able to provide.
4342 The libguestfs groups, and the functions that those
4343 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4344 You can also fetch this list at runtime by calling
4345 C<guestfs_available_all_groups>.
4347 The argument C<groups> is a list of group names, eg:
4348 C<[\"inotify\", \"augeas\"]> would check for the availability of
4349 the Linux inotify functions and Augeas (configuration file
4352 The command returns no error if I<all> requested groups are available.
4354 It fails with an error if one or more of the requested
4355 groups is unavailable in the appliance.
4357 If an unknown group name is included in the
4358 list of groups then an error is always returned.
4366 You must call C<guestfs_launch> before calling this function.
4368 The reason is because we don't know what groups are
4369 supported by the appliance/daemon until it is running and can
4374 If a group of functions is available, this does not necessarily
4375 mean that they will work. You still have to check for errors
4376 when calling individual API functions even if they are
4381 It is usually the job of distro packagers to build
4382 complete functionality into the libguestfs appliance.
4383 Upstream libguestfs, if built from source with all
4384 requirements satisfied, will support everything.
4388 This call was added in version C<1.0.80>. In previous
4389 versions of libguestfs all you could do would be to speculatively
4390 execute a command to find out if the daemon implemented it.
4391 See also C<guestfs_version>.
4395 ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4396 [InitBasicFS, Always, TestOutputBuffer (
4397 [["write"; "/src"; "hello, world"];
4398 ["dd"; "/src"; "/dest"];
4399 ["read_file"; "/dest"]], "hello, world")],
4400 "copy from source to destination using dd",
4402 This command copies from one source device or file C<src>
4403 to another destination device or file C<dest>. Normally you
4404 would use this to copy to or from a device or partition, for
4405 example to duplicate a filesystem.
4407 If the destination is a device, it must be as large or larger
4408 than the source file or device, otherwise the copy will fail.
4409 This command cannot do partial copies (see C<guestfs_copy_size>).");
4411 ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4412 [InitBasicFS, Always, TestOutputInt (
4413 [["write"; "/file"; "hello, world"];
4414 ["filesize"; "/file"]], 12)],
4415 "return the size of the file in bytes",
4417 This command returns the size of C<file> in bytes.
4419 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4420 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4421 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4423 ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4424 [InitBasicFSonLVM, Always, TestOutputList (
4425 [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4426 ["lvs"]], ["/dev/VG/LV2"])],
4427 "rename an LVM logical volume",
4429 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4431 ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4432 [InitBasicFSonLVM, Always, TestOutputList (
4434 ["vg_activate"; "false"; "VG"];
4435 ["vgrename"; "VG"; "VG2"];
4436 ["vg_activate"; "true"; "VG2"];
4437 ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4438 ["vgs"]], ["VG2"])],
4439 "rename an LVM volume group",
4441 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4443 ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4444 [InitISOFS, Always, TestOutputBuffer (
4445 [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4446 "list the contents of a single file in an initrd",
4448 This command unpacks the file C<filename> from the initrd file
4449 called C<initrdpath>. The filename must be given I<without> the
4450 initial C</> character.
4452 For example, in guestfish you could use the following command
4453 to examine the boot script (usually called C</init>)
4454 contained in a Linux initrd or initramfs image:
4456 initrd-cat /boot/initrd-<version>.img init
4458 See also C<guestfs_initrd_list>.");
4460 ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4462 "get the UUID of a physical volume",
4464 This command returns the UUID of the LVM PV C<device>.");
4466 ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4468 "get the UUID of a volume group",
4470 This command returns the UUID of the LVM VG named C<vgname>.");
4472 ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4474 "get the UUID of a logical volume",
4476 This command returns the UUID of the LVM LV C<device>.");
4478 ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4480 "get the PV UUIDs containing the volume group",
4482 Given a VG called C<vgname>, this returns the UUIDs of all
4483 the physical volumes that this volume group resides on.
4485 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4486 calls to associate physical volumes and volume groups.
4488 See also C<guestfs_vglvuuids>.");
4490 ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4492 "get the LV UUIDs of all LVs in the volume group",
4494 Given a VG called C<vgname>, this returns the UUIDs of all
4495 the logical volumes created in this volume group.
4497 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4498 calls to associate logical volumes and volume groups.
4500 See also C<guestfs_vgpvuuids>.");
4502 ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4503 [InitBasicFS, Always, TestOutputBuffer (
4504 [["write"; "/src"; "hello, world"];
4505 ["copy_size"; "/src"; "/dest"; "5"];
4506 ["read_file"; "/dest"]], "hello")],
4507 "copy size bytes from source to destination using dd",
4509 This command copies exactly C<size> bytes from one source device
4510 or file C<src> to another destination device or file C<dest>.
4512 Note this will fail if the source is too short or if the destination
4513 is not large enough.");
4515 ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4516 [InitBasicFSonLVM, Always, TestRun (
4517 [["zero_device"; "/dev/VG/LV"]])],
4518 "write zeroes to an entire device",
4520 This command writes zeroes over the entire C<device>. Compare
4521 with C<guestfs_zero> which just zeroes the first few blocks of
4524 ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4525 [InitBasicFS, Always, TestOutput (
4526 [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4527 ["cat"; "/hello"]], "hello\n")],
4528 "unpack compressed tarball to directory",
4530 This command uploads and unpacks local file C<tarball> (an
4531 I<xz compressed> tar file) into C<directory>.");
4533 ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4535 "pack directory into compressed tarball",
4537 This command packs the contents of C<directory> and downloads
4538 it to local file C<tarball> (as an xz compressed tar archive).");
4540 ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4542 "resize an NTFS filesystem",
4544 This command resizes an NTFS filesystem, expanding or
4545 shrinking it to the size of the underlying device.
4546 See also L<ntfsresize(8)>.");
4548 ("vgscan", (RErr, []), 232, [],
4549 [InitEmpty, Always, TestRun (
4551 "rescan for LVM physical volumes, volume groups and logical volumes",
4553 This rescans all block devices and rebuilds the list of LVM
4554 physical volumes, volume groups and logical volumes.");
4556 ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4557 [InitEmpty, Always, TestRun (
4558 [["part_init"; "/dev/sda"; "mbr"];
4559 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4560 ["part_del"; "/dev/sda"; "1"]])],
4561 "delete a partition",
4563 This command deletes the partition numbered C<partnum> on C<device>.
4565 Note that in the case of MBR partitioning, deleting an
4566 extended partition also deletes any logical partitions
4569 ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4570 [InitEmpty, Always, TestOutputTrue (
4571 [["part_init"; "/dev/sda"; "mbr"];
4572 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4573 ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4574 ["part_get_bootable"; "/dev/sda"; "1"]])],
4575 "return true if a partition is bootable",
4577 This command returns true if the partition C<partnum> on
4578 C<device> has the bootable flag set.
4580 See also C<guestfs_part_set_bootable>.");
4582 ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4583 [InitEmpty, Always, TestOutputInt (
4584 [["part_init"; "/dev/sda"; "mbr"];
4585 ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4586 ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4587 ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4588 "get the MBR type byte (ID byte) from a partition",
4590 Returns the MBR type byte (also known as the ID byte) from
4591 the numbered partition C<partnum>.
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4597 ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4598 [], (* tested by part_get_mbr_id *)
4599 "set the MBR type byte (ID byte) of a partition",
4601 Sets the MBR type byte (also known as the ID byte) of
4602 the numbered partition C<partnum> to C<idbyte>. Note
4603 that the type bytes quoted in most documentation are
4604 in fact hexadecimal numbers, but usually documented
4605 without any leading \"0x\" which might be confusing.
4607 Note that only MBR (old DOS-style) partitions have type bytes.
4608 You will get undefined results for other partition table
4609 types (see C<guestfs_part_get_parttype>).");
4611 ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4612 [InitISOFS, Always, TestOutput (
4613 [["checksum_device"; "md5"; "/dev/sdd"]],
4614 (Digest.to_hex (Digest.file "images/test.iso")))],
4615 "compute MD5, SHAx or CRC checksum of the contents of a device",
4617 This call computes the MD5, SHAx or CRC checksum of the
4618 contents of the device named C<device>. For the types of
4619 checksums supported see the C<guestfs_checksum> command.");
4621 ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4622 [InitNone, Always, TestRun (
4623 [["part_disk"; "/dev/sda"; "mbr"];
4624 ["pvcreate"; "/dev/sda1"];
4625 ["vgcreate"; "VG"; "/dev/sda1"];
4626 ["lvcreate"; "LV"; "VG"; "10"];
4627 ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4628 "expand an LV to fill free space",
4630 This expands an existing logical volume C<lv> so that it fills
4631 C<pc>% of the remaining free space in the volume group. Commonly
4632 you would call this with pc = 100 which expands the logical volume
4633 as much as possible, using all remaining free space in the volume
4636 ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4637 [], (* XXX Augeas code needs tests. *)
4638 "clear Augeas path",
4640 Set the value associated with C<path> to C<NULL>. This
4641 is the same as the L<augtool(1)> C<clear> command.");
4643 ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4644 [InitEmpty, Always, TestOutputInt (
4645 [["get_umask"]], 0o22)],
4646 "get the current umask",
4648 Return the current umask. By default the umask is C<022>
4649 unless it has been set by calling C<guestfs_umask>.");
4651 ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4653 "upload a file to the appliance (internal use only)",
4655 The C<guestfs_debug_upload> command uploads a file to
4656 the libguestfs appliance.
4658 There is no comprehensive help for this command. You have
4659 to look at the file C<daemon/debug.c> in the libguestfs source
4660 to find out what it is for.");
4662 ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4663 [InitBasicFS, Always, TestOutput (
4664 [["base64_in"; "../images/hello.b64"; "/hello"];
4665 ["cat"; "/hello"]], "hello\n")],
4666 "upload base64-encoded data to file",
4668 This command uploads base64-encoded data from C<base64file>
4671 ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4673 "download file and encode as base64",
4675 This command downloads the contents of C<filename>, writing
4676 it out to local file C<base64file> encoded as base64.");
4678 ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4680 "compute MD5, SHAx or CRC checksum of files in a directory",
4682 This command computes the checksums of all regular files in
4683 C<directory> and then emits a list of those checksums to
4684 the local output file C<sumsfile>.
4686 This can be used for verifying the integrity of a virtual
4687 machine. However to be properly secure you should pay
4688 attention to the output of the checksum command (it uses
4689 the ones from GNU coreutils). In particular when the
4690 filename is not printable, coreutils uses a special
4691 backslash syntax. For more information, see the GNU
4692 coreutils info file.");
4694 ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4695 [InitBasicFS, Always, TestOutputBuffer (
4696 [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4697 ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4698 "fill a file with a repeating pattern of bytes",
4700 This function is like C<guestfs_fill> except that it creates
4701 a new file of length C<len> containing the repeating pattern
4702 of bytes in C<pattern>. The pattern is truncated if necessary
4703 to ensure the length of the file is exactly C<len> bytes.");
4705 ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4706 [InitBasicFS, Always, TestOutput (
4707 [["write"; "/new"; "new file contents"];
4708 ["cat"; "/new"]], "new file contents");
4709 InitBasicFS, Always, TestOutput (
4710 [["write"; "/new"; "\nnew file contents\n"];
4711 ["cat"; "/new"]], "\nnew file contents\n");
4712 InitBasicFS, Always, TestOutput (
4713 [["write"; "/new"; "\n\n"];
4714 ["cat"; "/new"]], "\n\n");
4715 InitBasicFS, Always, TestOutput (
4716 [["write"; "/new"; ""];
4717 ["cat"; "/new"]], "");
4718 InitBasicFS, Always, TestOutput (
4719 [["write"; "/new"; "\n\n\n"];
4720 ["cat"; "/new"]], "\n\n\n");
4721 InitBasicFS, Always, TestOutput (
4722 [["write"; "/new"; "\n"];
4723 ["cat"; "/new"]], "\n")],
4724 "create a new file",
4726 This call creates a file called C<path>. The content of the
4727 file is the string C<content> (which can contain any 8 bit data).");
4729 ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4730 [InitBasicFS, Always, TestOutput (
4731 [["write"; "/new"; "new file contents"];
4732 ["pwrite"; "/new"; "data"; "4"];
4733 ["cat"; "/new"]], "new data contents");
4734 InitBasicFS, Always, TestOutput (
4735 [["write"; "/new"; "new file contents"];
4736 ["pwrite"; "/new"; "is extended"; "9"];
4737 ["cat"; "/new"]], "new file is extended");
4738 InitBasicFS, Always, TestOutput (
4739 [["write"; "/new"; "new file contents"];
4740 ["pwrite"; "/new"; ""; "4"];
4741 ["cat"; "/new"]], "new file contents")],
4742 "write to part of a file",
4744 This command writes to part of a file. It writes the data
4745 buffer C<content> to the file C<path> starting at offset C<offset>.
4747 This command implements the L<pwrite(2)> system call, and like
4748 that system call it may not write the full data requested. The
4749 return value is the number of bytes that were actually written
4750 to the file. This could even be 0, although short writes are
4751 unlikely for regular files in ordinary circumstances.
4753 See also C<guestfs_pread>.");
4755 ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4757 "resize an ext2, ext3 or ext4 filesystem (with size)",
4759 This command is the same as C<guestfs_resize2fs> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4762 ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4764 "resize an LVM physical volume (with size)",
4766 This command is the same as C<guestfs_pvresize> except that it
4767 allows you to specify the new size (in bytes) explicitly.");
4769 ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4771 "resize an NTFS filesystem (with size)",
4773 This command is the same as C<guestfs_ntfsresize> except that it
4774 allows you to specify the new size (in bytes) explicitly.");
4776 ("available_all_groups", (RStringList "groups", []), 251, [],
4777 [InitNone, Always, TestRun [["available_all_groups"]]],
4778 "return a list of all optional groups",
4780 This command returns a list of all optional groups that this
4781 daemon knows about. Note this returns both supported and unsupported
4782 groups. To find out which ones the daemon can actually support
4783 you have to call C<guestfs_available> on each member of the
4786 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4788 ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4789 [InitBasicFS, Always, TestOutputStruct (
4790 [["fallocate64"; "/a"; "1000000"];
4791 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4792 "preallocate a file in the guest filesystem",
4794 This command preallocates a file (containing zero bytes) named
4795 C<path> of size C<len> bytes. If the file exists already, it
4798 Note that this call allocates disk blocks for the file.
4799 To create a sparse file use C<guestfs_truncate_size> instead.
4801 The deprecated call C<guestfs_fallocate> does the same,
4802 but owing to an oversight it only allowed 30 bit lengths
4803 to be specified, effectively limiting the maximum size
4804 of files created through that call to 1GB.
4806 Do not confuse this with the guestfish-specific
4807 C<alloc> and C<sparse> commands which create
4808 a file in the host and attach it as a device.");
4810 ("vfs_label", (RString "label", [Device "device"]), 253, [],
4811 [InitBasicFS, Always, TestOutput (
4812 [["set_e2label"; "/dev/sda1"; "LTEST"];
4813 ["vfs_label"; "/dev/sda1"]], "LTEST")],
4814 "get the filesystem label",
4816 This returns the filesystem label of the filesystem on
4819 If the filesystem is unlabeled, this returns the empty string.");
4821 ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4822 (let uuid = uuidgen () in
4823 [InitBasicFS, Always, TestOutput (
4824 [["set_e2uuid"; "/dev/sda1"; uuid];
4825 ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4826 "get the filesystem UUID",
4828 This returns the filesystem UUID of the filesystem on
4831 If the filesystem does not have a UUID, this returns the empty string.");
4835 let all_functions = non_daemon_functions @ daemon_functions
4837 (* In some places we want the functions to be displayed sorted
4838 * alphabetically, so this is useful:
4840 let all_functions_sorted =
4841 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4842 compare n1 n2) all_functions
4844 (* This is used to generate the src/MAX_PROC_NR file which
4845 * contains the maximum procedure number, a surrogate for the
4846 * ABI version number. See src/Makefile.am for the details.
4849 let proc_nrs = List.map (
4850 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4851 ) daemon_functions in
4852 List.fold_left max 0 proc_nrs
4854 (* Field types for structures. *)
4856 | FChar (* C 'char' (really, a 7 bit byte). *)
4857 | FString (* nul-terminated ASCII string, NOT NULL. *)
4858 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
4863 | FBytes (* Any int measure that counts bytes. *)
4864 | FUUID (* 32 bytes long, NOT nul-terminated. *)
4865 | FOptPercent (* [0..100], or -1 meaning "not present". *)
4867 (* Because we generate extra parsing code for LVM command line tools,
4868 * we have to pull out the LVM columns separately here.
4878 "pv_attr", FString (* XXX *);
4879 "pv_pe_count", FInt64;
4880 "pv_pe_alloc_count", FInt64;
4883 "pv_mda_count", FInt64;
4884 "pv_mda_free", FBytes;
4885 (* Not in Fedora 10:
4886 "pv_mda_size", FBytes;
4893 "vg_attr", FString (* XXX *);
4896 "vg_sysid", FString;
4897 "vg_extent_size", FBytes;
4898 "vg_extent_count", FInt64;
4899 "vg_free_count", FInt64;
4904 "snap_count", FInt64;
4907 "vg_mda_count", FInt64;
4908 "vg_mda_free", FBytes;
4909 (* Not in Fedora 10:
4910 "vg_mda_size", FBytes;
4916 "lv_attr", FString (* XXX *);
4919 "lv_kernel_major", FInt64;
4920 "lv_kernel_minor", FInt64;
4922 "seg_count", FInt64;
4924 "snap_percent", FOptPercent;
4925 "copy_percent", FOptPercent;
4928 "mirror_log", FString;
4932 (* Names and fields in all structures (in RStruct and RStructList)
4936 (* The old RIntBool return type, only ever used for aug_defnode. Do
4937 * not use this struct in any new code.
4940 "i", FInt32; (* for historical compatibility *)
4941 "b", FInt32; (* for historical compatibility *)
4944 (* LVM PVs, VGs, LVs. *)
4945 "lvm_pv", lvm_pv_cols;
4946 "lvm_vg", lvm_vg_cols;
4947 "lvm_lv", lvm_lv_cols;
4949 (* Column names and types from stat structures.
4950 * NB. Can't use things like 'st_atime' because glibc header files
4951 * define some of these as macros. Ugh.
4982 (* Column names in dirent structure. *)
4985 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4990 (* Version numbers. *)
4998 (* Extended attribute. *)
5000 "attrname", FString;
5004 (* Inotify events. *)
5008 "in_cookie", FUInt32;
5012 (* Partition table entry. *)
5015 "part_start", FBytes;
5017 "part_size", FBytes;
5019 ] (* end of structs *)
5021 (* Ugh, Java has to be different ..
5022 * These names are also used by the Haskell bindings.
5024 let java_structs = [
5025 "int_bool", "IntBool";
5030 "statvfs", "StatVFS";
5032 "version", "Version";
5034 "inotify_event", "INotifyEvent";
5035 "partition", "Partition";
5038 (* What structs are actually returned. *)
5039 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5041 (* Returns a list of RStruct/RStructList structs that are returned
5042 * by any function. Each element of returned list is a pair:
5044 * (structname, RStructOnly)
5045 * == there exists function which returns RStruct (_, structname)
5046 * (structname, RStructListOnly)
5047 * == there exists function which returns RStructList (_, structname)
5048 * (structname, RStructAndList)
5049 * == there are functions returning both RStruct (_, structname)
5050 * and RStructList (_, structname)
5052 let rstructs_used_by functions =
5053 (* ||| is a "logical OR" for rstructs_used_t *)
5057 | _, RStructAndList -> RStructAndList
5058 | RStructOnly, RStructListOnly
5059 | RStructListOnly, RStructOnly -> RStructAndList
5060 | RStructOnly, RStructOnly -> RStructOnly
5061 | RStructListOnly, RStructListOnly -> RStructListOnly
5064 let h = Hashtbl.create 13 in
5066 (* if elem->oldv exists, update entry using ||| operator,
5067 * else just add elem->newv to the hash
5069 let update elem newv =
5070 try let oldv = Hashtbl.find h elem in
5071 Hashtbl.replace h elem (newv ||| oldv)
5072 with Not_found -> Hashtbl.add h elem newv
5076 fun (_, style, _, _, _, _, _) ->
5077 match fst style with
5078 | RStruct (_, structname) -> update structname RStructOnly
5079 | RStructList (_, structname) -> update structname RStructListOnly
5083 (* return key->values as a list of (key,value) *)
5084 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5086 (* Used for testing language bindings. *)
5088 | CallString of string
5089 | CallOptString of string option
5090 | CallStringList of string list
5092 | CallInt64 of int64
5094 | CallBuffer of string
5096 (* Used to memoize the result of pod2text. *)
5097 let pod2text_memo_filename = "src/.pod2text.data"
5098 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5100 let chan = open_in pod2text_memo_filename in
5101 let v = input_value chan in
5105 _ -> Hashtbl.create 13
5106 let pod2text_memo_updated () =
5107 let chan = open_out pod2text_memo_filename in
5108 output_value chan pod2text_memo;
5111 (* Useful functions.
5112 * Note we don't want to use any external OCaml libraries which
5113 * makes this a bit harder than it should be.
5115 module StringMap = Map.Make (String)
5117 let failwithf fs = ksprintf failwith fs
5119 let unique = let i = ref 0 in fun () -> incr i; !i
5121 let replace_char s c1 c2 =
5122 let s2 = String.copy s in
5123 let r = ref false in
5124 for i = 0 to String.length s2 - 1 do
5125 if String.unsafe_get s2 i = c1 then (
5126 String.unsafe_set s2 i c2;
5130 if not !r then s else s2
5134 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5136 let triml ?(test = isspace) str =
5138 let n = ref (String.length str) in
5139 while !n > 0 && test str.[!i]; do
5144 else String.sub str !i !n
5146 let trimr ?(test = isspace) str =
5147 let n = ref (String.length str) in
5148 while !n > 0 && test str.[!n-1]; do
5151 if !n = String.length str then str
5152 else String.sub str 0 !n
5154 let trim ?(test = isspace) str =
5155 trimr ~test (triml ~test str)
5157 let rec find s sub =
5158 let len = String.length s in
5159 let sublen = String.length sub in
5161 if i <= len-sublen then (
5163 if j < sublen then (
5164 if s.[i+j] = sub.[j] then loop2 (j+1)
5170 if r = -1 then loop (i+1) else r
5176 let rec replace_str s s1 s2 =
5177 let len = String.length s in
5178 let sublen = String.length s1 in
5179 let i = find s s1 in
5182 let s' = String.sub s 0 i in
5183 let s'' = String.sub s (i+sublen) (len-i-sublen) in
5184 s' ^ s2 ^ replace_str s'' s1 s2
5187 let rec string_split sep str =
5188 let len = String.length str in
5189 let seplen = String.length sep in
5190 let i = find str sep in
5191 if i = -1 then [str]
5193 let s' = String.sub str 0 i in
5194 let s'' = String.sub str (i+seplen) (len-i-seplen) in
5195 s' :: string_split sep s''
5198 let files_equal n1 n2 =
5199 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5200 match Sys.command cmd with
5203 | i -> failwithf "%s: failed with error code %d" cmd i
5205 let rec filter_map f = function
5209 | Some y -> y :: filter_map f xs
5210 | None -> filter_map f xs
5212 let rec find_map f = function
5213 | [] -> raise Not_found
5217 | None -> find_map f xs
5220 let rec loop i = function
5222 | x :: xs -> f i x; loop (i+1) xs
5227 let rec loop i = function
5229 | x :: xs -> let r = f i x in r :: loop (i+1) xs
5233 let count_chars c str =
5234 let count = ref 0 in
5235 for i = 0 to String.length str - 1 do
5236 if c = String.unsafe_get str i then incr count
5242 for i = 0 to String.length str - 1 do
5243 let c = String.unsafe_get str i in
5248 let map_chars f str =
5249 List.map f (explode str)
5251 let name_of_argt = function
5252 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5253 | StringList n | DeviceList n | Bool n | Int n | Int64 n
5254 | FileIn n | FileOut n | BufferIn n -> n
5256 let java_name_of_struct typ =
5257 try List.assoc typ java_structs
5260 "java_name_of_struct: no java_structs entry corresponding to %s" typ
5262 let cols_of_struct typ =
5263 try List.assoc typ structs
5265 failwithf "cols_of_struct: unknown struct %s" typ
5267 let seq_of_test = function
5268 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5269 | TestOutputListOfDevices (s, _)
5270 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5271 | TestOutputTrue s | TestOutputFalse s
5272 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5273 | TestOutputStruct (s, _)
5274 | TestLastFail s -> s
5276 (* Handling for function flags. *)
5277 let protocol_limit_warning =
5278 "Because of the message protocol, there is a transfer limit
5279 of somewhere between 2MB and 4MB. See L<guestfs(3)/PROTOCOL LIMITS>."
5281 let danger_will_robinson =
5282 "B<This command is dangerous. Without careful use you
5283 can easily destroy all your data>."
5285 let deprecation_notice flags =
5288 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5290 sprintf "This function is deprecated.
5291 In new code, use the C<%s> call instead.
5293 Deprecated functions will not be removed from the API, but the
5294 fact that they are deprecated indicates that there are problems
5295 with correct use of these functions." alt in
5300 (* Create list of optional groups. *)
5302 let h = Hashtbl.create 13 in
5304 fun (name, _, _, flags, _, _, _) ->
5308 let names = try Hashtbl.find h group with Not_found -> [] in
5309 Hashtbl.replace h group (name :: names)
5313 let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5316 fun group -> group, List.sort compare (Hashtbl.find h group)
5318 List.sort (fun x y -> compare (fst x) (fst y)) groups
5320 (* Check function names etc. for consistency. *)
5321 let check_functions () =
5322 let contains_uppercase str =
5323 let len = String.length str in
5325 if i >= len then false
5328 if c >= 'A' && c <= 'Z' then true
5335 (* Check function names. *)
5337 fun (name, _, _, _, _, _, _) ->
5338 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5339 failwithf "function name %s does not need 'guestfs' prefix" name;
5341 failwithf "function name is empty";
5342 if name.[0] < 'a' || name.[0] > 'z' then
5343 failwithf "function name %s must start with lowercase a-z" name;
5344 if String.contains name '-' then
5345 failwithf "function name %s should not contain '-', use '_' instead."
5349 (* Check function parameter/return names. *)
5351 fun (name, style, _, _, _, _, _) ->
5352 let check_arg_ret_name n =
5353 if contains_uppercase n then
5354 failwithf "%s param/ret %s should not contain uppercase chars"
5356 if String.contains n '-' || String.contains n '_' then
5357 failwithf "%s param/ret %s should not contain '-' or '_'"
5360 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;
5361 if n = "int" || n = "char" || n = "short" || n = "long" then
5362 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5363 if n = "i" || n = "n" then
5364 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5365 if n = "argv" || n = "args" then
5366 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5368 (* List Haskell, OCaml and C keywords here.
5369 * http://www.haskell.org/haskellwiki/Keywords
5370 * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5371 * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5372 * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5373 * |perl -pe 's/(.+)/"$1";/'|fmt -70
5374 * Omitting _-containing words, since they're handled above.
5375 * Omitting the OCaml reserved word, "val", is ok,
5376 * and saves us from renaming several parameters.
5379 "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5380 "char"; "class"; "const"; "constraint"; "continue"; "data";
5381 "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5382 "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5383 "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5384 "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5385 "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5387 "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5388 "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5389 "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5390 "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5391 "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5392 "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5393 "volatile"; "when"; "where"; "while";
5395 if List.mem n reserved then
5396 failwithf "%s has param/ret using reserved word %s" name n;
5399 (match fst style with
5401 | RInt n | RInt64 n | RBool n
5402 | RConstString n | RConstOptString n | RString n
5403 | RStringList n | RStruct (n, _) | RStructList (n, _)
5404 | RHashtable n | RBufferOut n ->
5405 check_arg_ret_name n
5407 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5410 (* Check short descriptions. *)
5412 fun (name, _, _, _, _, shortdesc, _) ->
5413 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5414 failwithf "short description of %s should begin with lowercase." name;
5415 let c = shortdesc.[String.length shortdesc-1] in
5416 if c = '\n' || c = '.' then
5417 failwithf "short description of %s should not end with . or \\n." name
5420 (* Check long descriptions. *)
5422 fun (name, _, _, _, _, _, longdesc) ->
5423 if longdesc.[String.length longdesc-1] = '\n' then
5424 failwithf "long description of %s should not end with \\n." name
5427 (* Check proc_nrs. *)
5429 fun (name, _, proc_nr, _, _, _, _) ->
5430 if proc_nr <= 0 then
5431 failwithf "daemon function %s should have proc_nr > 0" name
5435 fun (name, _, proc_nr, _, _, _, _) ->
5436 if proc_nr <> -1 then
5437 failwithf "non-daemon function %s should have proc_nr -1" name
5438 ) non_daemon_functions;
5441 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5444 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5445 let rec loop = function
5448 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5450 | (name1,nr1) :: (name2,nr2) :: _ ->
5451 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5459 (* Ignore functions that have no tests. We generate a
5460 * warning when the user does 'make check' instead.
5462 | name, _, _, _, [], _, _ -> ()
5463 | name, _, _, _, tests, _, _ ->
5467 match seq_of_test test with
5469 failwithf "%s has a test containing an empty sequence" name
5470 | cmds -> List.map List.hd cmds
5472 let funcs = List.flatten funcs in
5474 let tested = List.mem name funcs in
5477 failwithf "function %s has tests but does not test itself" name
5480 (* 'pr' prints to the current output file. *)
5481 let chan = ref Pervasives.stdout
5486 let i = count_chars '\n' str in
5487 lines := !lines + i;
5488 output_string !chan str
5491 let copyright_years =
5492 let this_year = 1900 + (localtime (time ())).tm_year in
5493 if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5495 (* Generate a header block in a number of standard styles. *)
5496 type comment_style =
5497 CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5498 type license = GPLv2plus | LGPLv2plus
5500 let generate_header ?(extra_inputs = []) comment license =
5501 let inputs = "src/generator.ml" :: extra_inputs in
5502 let c = match comment with
5503 | CStyle -> pr "/* "; " *"
5504 | CPlusPlusStyle -> pr "// "; "//"
5505 | HashStyle -> pr "# "; "#"
5506 | OCamlStyle -> pr "(* "; " *"
5507 | HaskellStyle -> pr "{- "; " " in
5508 pr "libguestfs generated file\n";
5509 pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5510 List.iter (pr "%s %s\n" c) inputs;
5511 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5513 pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5517 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5518 pr "%s it under the terms of the GNU General Public License as published by\n" c;
5519 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5520 pr "%s (at your option) any later version.\n" c;
5522 pr "%s This program is distributed in the hope that it will be useful,\n" c;
5523 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5524 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
5525 pr "%s GNU General Public License for more details.\n" c;
5527 pr "%s You should have received a copy of the GNU General Public License along\n" c;
5528 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5529 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5532 pr "%s This library is free software; you can redistribute it and/or\n" c;
5533 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5534 pr "%s License as published by the Free Software Foundation; either\n" c;
5535 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5537 pr "%s This library is distributed in the hope that it will be useful,\n" c;
5538 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5539 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
5540 pr "%s Lesser General Public License for more details.\n" c;
5542 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5543 pr "%s License along with this library; if not, write to the Free Software\n" c;
5544 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5547 | CStyle -> pr " */\n"
5550 | OCamlStyle -> pr " *)\n"
5551 | HaskellStyle -> pr "-}\n"
5555 (* Start of main code generation functions below this line. *)
5557 (* Generate the pod documentation for the C API. *)
5558 let rec generate_actions_pod () =
5560 fun (shortname, style, _, flags, _, _, longdesc) ->
5561 if not (List.mem NotInDocs flags) then (
5562 let name = "guestfs_" ^ shortname in
5563 pr "=head2 %s\n\n" name;
5565 generate_prototype ~extern:false ~handle:"g" name style;
5567 pr "%s\n\n" longdesc;
5568 (match fst style with
5570 pr "This function returns 0 on success or -1 on error.\n\n"
5572 pr "On error this function returns -1.\n\n"
5574 pr "On error this function returns -1.\n\n"
5576 pr "This function returns a C truth value on success or -1 on error.\n\n"
5578 pr "This function returns a string, or NULL on error.
5579 The string is owned by the guest handle and must I<not> be freed.\n\n"
5580 | RConstOptString _ ->
5581 pr "This function returns a string which may be NULL.
5582 There is way to return an error from this function.
5583 The string is owned by the guest handle and must I<not> be freed.\n\n"
5585 pr "This function returns a string, or NULL on error.
5586 I<The caller must free the returned string after use>.\n\n"
5588 pr "This function returns a NULL-terminated array of strings
5589 (like L<environ(3)>), or NULL if there was an error.
5590 I<The caller must free the strings and the array after use>.\n\n"
5591 | RStruct (_, typ) ->
5592 pr "This function returns a C<struct guestfs_%s *>,
5593 or NULL if there was an error.
5594 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5595 | RStructList (_, typ) ->
5596 pr "This function returns a C<struct guestfs_%s_list *>
5597 (see E<lt>guestfs-structs.hE<gt>),
5598 or NULL if there was an error.
5599 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5601 pr "This function returns a NULL-terminated array of
5602 strings, or NULL if there was an error.
5603 The array of strings will always have length C<2n+1>, where
5604 C<n> keys and values alternate, followed by the trailing NULL entry.
5605 I<The caller must free the strings and the array after use>.\n\n"
5607 pr "This function returns a buffer, or NULL on error.
5608 The size of the returned buffer is written to C<*size_r>.
5609 I<The caller must free the returned buffer after use>.\n\n"
5611 if List.mem ProtocolLimitWarning flags then
5612 pr "%s\n\n" protocol_limit_warning;
5613 if List.mem DangerWillRobinson flags then
5614 pr "%s\n\n" danger_will_robinson;
5615 match deprecation_notice flags with
5617 | Some txt -> pr "%s\n\n" txt
5619 ) all_functions_sorted
5621 and generate_structs_pod () =
5622 (* Structs documentation. *)
5625 pr "=head2 guestfs_%s\n" typ;
5627 pr " struct guestfs_%s {\n" typ;
5630 | name, FChar -> pr " char %s;\n" name
5631 | name, FUInt32 -> pr " uint32_t %s;\n" name
5632 | name, FInt32 -> pr " int32_t %s;\n" name
5633 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5634 | name, FInt64 -> pr " int64_t %s;\n" name
5635 | name, FString -> pr " char *%s;\n" name
5637 pr " /* The next two fields describe a byte array. */\n";
5638 pr " uint32_t %s_len;\n" name;
5639 pr " char *%s;\n" name
5641 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5642 pr " char %s[32];\n" name
5643 | name, FOptPercent ->
5644 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
5645 pr " float %s;\n" name
5649 pr " struct guestfs_%s_list {\n" typ;
5650 pr " uint32_t len; /* Number of elements in list. */\n";
5651 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
5654 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5655 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5660 and generate_availability_pod () =
5661 (* Availability documentation. *)
5665 fun (group, functions) ->
5666 pr "=item B<%s>\n" group;
5668 pr "The following functions:\n";
5669 List.iter (pr "L</guestfs_%s>\n") functions;
5675 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5676 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5678 * We have to use an underscore instead of a dash because otherwise
5679 * rpcgen generates incorrect code.
5681 * This header is NOT exported to clients, but see also generate_structs_h.
5683 and generate_xdr () =
5684 generate_header CStyle LGPLv2plus;
5686 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5687 pr "typedef string str<>;\n";
5690 (* Internal structures. *)
5694 pr "struct guestfs_int_%s {\n" typ;
5696 | name, FChar -> pr " char %s;\n" name
5697 | name, FString -> pr " string %s<>;\n" name
5698 | name, FBuffer -> pr " opaque %s<>;\n" name
5699 | name, FUUID -> pr " opaque %s[32];\n" name
5700 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
5701 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
5702 | name, FOptPercent -> pr " float %s;\n" name
5706 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5711 fun (shortname, style, _, _, _, _, _) ->
5712 let name = "guestfs_" ^ shortname in
5714 (match snd style with
5717 pr "struct %s_args {\n" name;
5720 | Pathname n | Device n | Dev_or_Path n | String n ->
5721 pr " string %s<>;\n" n
5722 | OptString n -> pr " str *%s;\n" n
5723 | StringList n | DeviceList n -> pr " str %s<>;\n" n
5724 | Bool n -> pr " bool %s;\n" n
5725 | Int n -> pr " int %s;\n" n
5726 | Int64 n -> pr " hyper %s;\n" n
5728 pr " opaque %s<>;\n" n
5729 | FileIn _ | FileOut _ -> ()
5733 (match fst style with
5736 pr "struct %s_ret {\n" name;
5740 pr "struct %s_ret {\n" name;
5741 pr " hyper %s;\n" n;
5744 pr "struct %s_ret {\n" name;
5747 | RConstString _ | RConstOptString _ ->
5748 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5750 pr "struct %s_ret {\n" name;
5751 pr " string %s<>;\n" n;
5754 pr "struct %s_ret {\n" name;
5755 pr " str %s<>;\n" n;
5757 | RStruct (n, typ) ->
5758 pr "struct %s_ret {\n" name;
5759 pr " guestfs_int_%s %s;\n" typ n;
5761 | RStructList (n, typ) ->
5762 pr "struct %s_ret {\n" name;
5763 pr " guestfs_int_%s_list %s;\n" typ n;
5766 pr "struct %s_ret {\n" name;
5767 pr " str %s<>;\n" n;
5770 pr "struct %s_ret {\n" name;
5771 pr " opaque %s<>;\n" n;
5776 (* Table of procedure numbers. *)
5777 pr "enum guestfs_procedure {\n";
5779 fun (shortname, _, proc_nr, _, _, _, _) ->
5780 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5782 pr " GUESTFS_PROC_NR_PROCS\n";
5786 (* Having to choose a maximum message size is annoying for several
5787 * reasons (it limits what we can do in the API), but it (a) makes
5788 * the protocol a lot simpler, and (b) provides a bound on the size
5789 * of the daemon which operates in limited memory space.
5791 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5794 (* Message header, etc. *)
5796 /* The communication protocol is now documented in the guestfs(3)
5800 const GUESTFS_PROGRAM = 0x2000F5F5;
5801 const GUESTFS_PROTOCOL_VERSION = 1;
5803 /* These constants must be larger than any possible message length. */
5804 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5805 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5807 enum guestfs_message_direction {
5808 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
5809 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
5812 enum guestfs_message_status {
5813 GUESTFS_STATUS_OK = 0,
5814 GUESTFS_STATUS_ERROR = 1
5817 const GUESTFS_ERROR_LEN = 256;
5819 struct guestfs_message_error {
5820 string error_message<GUESTFS_ERROR_LEN>;
5823 struct guestfs_message_header {
5824 unsigned prog; /* GUESTFS_PROGRAM */
5825 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
5826 guestfs_procedure proc; /* GUESTFS_PROC_x */
5827 guestfs_message_direction direction;
5828 unsigned serial; /* message serial number */
5829 guestfs_message_status status;
5832 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5834 struct guestfs_chunk {
5835 int cancel; /* if non-zero, transfer is cancelled */
5836 /* data size is 0 bytes if the transfer has finished successfully */
5837 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5841 (* Generate the guestfs-structs.h file. *)
5842 and generate_structs_h () =
5843 generate_header CStyle LGPLv2plus;
5845 (* This is a public exported header file containing various
5846 * structures. The structures are carefully written to have
5847 * exactly the same in-memory format as the XDR structures that
5848 * we use on the wire to the daemon. The reason for creating
5849 * copies of these structures here is just so we don't have to
5850 * export the whole of guestfs_protocol.h (which includes much
5851 * unrelated and XDR-dependent stuff that we don't want to be
5852 * public, or required by clients).
5854 * To reiterate, we will pass these structures to and from the
5855 * client with a simple assignment or memcpy, so the format
5856 * must be identical to what rpcgen / the RFC defines.
5859 (* Public structures. *)
5862 pr "struct guestfs_%s {\n" typ;
5865 | name, FChar -> pr " char %s;\n" name
5866 | name, FString -> pr " char *%s;\n" name
5868 pr " uint32_t %s_len;\n" name;
5869 pr " char *%s;\n" name
5870 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5871 | name, FUInt32 -> pr " uint32_t %s;\n" name
5872 | name, FInt32 -> pr " int32_t %s;\n" name
5873 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
5874 | name, FInt64 -> pr " int64_t %s;\n" name
5875 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
5879 pr "struct guestfs_%s_list {\n" typ;
5880 pr " uint32_t len;\n";
5881 pr " struct guestfs_%s *val;\n" typ;
5884 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5885 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5889 (* Generate the guestfs-actions.h file. *)
5890 and generate_actions_h () =
5891 generate_header CStyle LGPLv2plus;
5893 fun (shortname, style, _, _, _, _, _) ->
5894 let name = "guestfs_" ^ shortname in
5895 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5899 (* Generate the guestfs-internal-actions.h file. *)
5900 and generate_internal_actions_h () =
5901 generate_header CStyle LGPLv2plus;
5903 fun (shortname, style, _, _, _, _, _) ->
5904 let name = "guestfs__" ^ shortname in
5905 generate_prototype ~single_line:true ~newline:true ~handle:"g"
5907 ) non_daemon_functions
5909 (* Generate the client-side dispatch stubs. *)
5910 and generate_client_actions () =
5911 generate_header CStyle LGPLv2plus;
5918 #include <inttypes.h>
5920 #include \"guestfs.h\"
5921 #include \"guestfs-internal.h\"
5922 #include \"guestfs-internal-actions.h\"
5923 #include \"guestfs_protocol.h\"
5925 #define error guestfs_error
5926 //#define perrorf guestfs_perrorf
5927 #define safe_malloc guestfs_safe_malloc
5928 #define safe_realloc guestfs_safe_realloc
5929 //#define safe_strdup guestfs_safe_strdup
5930 #define safe_memdup guestfs_safe_memdup
5932 /* Check the return message from a call for validity. */
5934 check_reply_header (guestfs_h *g,
5935 const struct guestfs_message_header *hdr,
5936 unsigned int proc_nr, unsigned int serial)
5938 if (hdr->prog != GUESTFS_PROGRAM) {
5939 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5942 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5943 error (g, \"wrong protocol version (%%d/%%d)\",
5944 hdr->vers, GUESTFS_PROTOCOL_VERSION);
5947 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5948 error (g, \"unexpected message direction (%%d/%%d)\",
5949 hdr->direction, GUESTFS_DIRECTION_REPLY);
5952 if (hdr->proc != proc_nr) {
5953 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5956 if (hdr->serial != serial) {
5957 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5964 /* Check we are in the right state to run a high-level action. */
5966 check_state (guestfs_h *g, const char *caller)
5968 if (!guestfs__is_ready (g)) {
5969 if (guestfs__is_config (g) || guestfs__is_launching (g))
5970 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5973 error (g, \"%%s called from the wrong state, %%d != READY\",
5974 caller, guestfs__get_state (g));
5982 let error_code_of = function
5983 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5984 | RConstString _ | RConstOptString _
5985 | RString _ | RStringList _
5986 | RStruct _ | RStructList _
5987 | RHashtable _ | RBufferOut _ -> "NULL"
5990 (* Generate code to check String-like parameters are not passed in
5991 * as NULL (returning an error if they are).
5993 let check_null_strings shortname style =
5994 let pr_newline = ref false in
5997 (* parameters which should not be NULL *)
6007 pr " if (%s == NULL) {\n" n;
6008 pr " error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6009 pr " \"%s\", \"%s\");\n" shortname n;
6010 pr " return %s;\n" (error_code_of (fst style));
6017 (* not applicable *)
6023 if !pr_newline then pr "\n";
6026 (* Generate code to generate guestfish call traces. *)
6027 let trace_call shortname style =
6028 pr " if (guestfs__get_trace (g)) {\n";
6031 List.exists (function
6032 | StringList _ | DeviceList _ -> true
6033 | _ -> false) (snd style) in
6039 pr " printf (\"%s\");\n" shortname;
6042 | String n (* strings *)
6049 (* guestfish doesn't support string escaping, so neither do we *)
6050 pr " printf (\" \\\"%%s\\\"\", %s);\n" n
6051 | OptString n -> (* string option *)
6052 pr " if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6053 pr " else printf (\" null\");\n"
6055 | DeviceList n -> (* string list *)
6056 pr " putchar (' ');\n";
6057 pr " putchar ('\"');\n";
6058 pr " for (i = 0; %s[i]; ++i) {\n" n;
6059 pr " if (i > 0) putchar (' ');\n";
6060 pr " fputs (%s[i], stdout);\n" n;
6062 pr " putchar ('\"');\n";
6063 | Bool n -> (* boolean *)
6064 pr " fputs (%s ? \" true\" : \" false\", stdout);\n" n
6065 | Int n -> (* int *)
6066 pr " printf (\" %%d\", %s);\n" n
6068 pr " printf (\" %%\" PRIi64, %s);\n" n
6070 pr " putchar ('\\n');\n";
6075 (* For non-daemon functions, generate a wrapper around each function. *)
6077 fun (shortname, style, _, _, _, _, _) ->
6078 let name = "guestfs_" ^ shortname in
6080 generate_prototype ~extern:false ~semicolon:false ~newline:true
6081 ~handle:"g" name style;
6083 check_null_strings shortname style;
6084 trace_call shortname style;
6085 pr " return guestfs__%s " shortname;
6086 generate_c_call_args ~handle:"g" style;
6090 ) non_daemon_functions;
6092 (* Client-side stubs for each function. *)
6094 fun (shortname, style, _, _, _, _, _) ->
6095 let name = "guestfs_" ^ shortname in
6096 let error_code = error_code_of (fst style) in
6098 (* Generate the action stub. *)
6099 generate_prototype ~extern:false ~semicolon:false ~newline:true
6100 ~handle:"g" name style;
6104 (match snd style with
6106 | _ -> pr " struct %s_args args;\n" name
6109 pr " guestfs_message_header hdr;\n";
6110 pr " guestfs_message_error err;\n";
6112 match fst style with
6114 | RConstString _ | RConstOptString _ ->
6115 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6117 | RBool _ | RString _ | RStringList _
6118 | RStruct _ | RStructList _
6119 | RHashtable _ | RBufferOut _ ->
6120 pr " struct %s_ret ret;\n" name;
6123 pr " int serial;\n";
6126 check_null_strings shortname style;
6127 trace_call shortname style;
6128 pr " if (check_state (g, \"%s\") == -1) return %s;\n"
6129 shortname error_code;
6130 pr " guestfs___set_busy (g);\n";
6133 (* Send the main header and arguments. *)
6134 (match snd style with
6136 pr " serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6137 (String.uppercase shortname)
6141 | Pathname n | Device n | Dev_or_Path n | String n ->
6142 pr " args.%s = (char *) %s;\n" n n
6144 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
6145 | StringList n | DeviceList n ->
6146 pr " args.%s.%s_val = (char **) %s;\n" n n n;
6147 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6149 pr " args.%s = %s;\n" n n
6151 pr " args.%s = %s;\n" n n
6153 pr " args.%s = %s;\n" n n
6154 | FileIn _ | FileOut _ -> ()
6156 pr " /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6157 pr " if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6158 pr " error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6160 pr " guestfs___end_busy (g);\n";
6161 pr " return %s;\n" error_code;
6163 pr " args.%s.%s_val = (char *) %s;\n" n n n;
6164 pr " args.%s.%s_len = %s_size;\n" n n n
6166 pr " serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6167 (String.uppercase shortname);
6168 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6171 pr " if (serial == -1) {\n";
6172 pr " guestfs___end_busy (g);\n";
6173 pr " return %s;\n" error_code;
6177 (* Send any additional files (FileIn) requested. *)
6178 let need_read_reply_label = ref false in
6182 pr " r = guestfs___send_file (g, %s);\n" n;
6183 pr " if (r == -1) {\n";
6184 pr " guestfs___end_busy (g);\n";
6185 pr " return %s;\n" error_code;
6187 pr " if (r == -2) /* daemon cancelled */\n";
6188 pr " goto read_reply;\n";
6189 need_read_reply_label := true;
6194 (* Wait for the reply from the remote end. *)
6195 if !need_read_reply_label then pr " read_reply:\n";
6196 pr " memset (&hdr, 0, sizeof hdr);\n";
6197 pr " memset (&err, 0, sizeof err);\n";
6198 if has_ret then pr " memset (&ret, 0, sizeof ret);\n";
6200 pr " r = guestfs___recv (g, \"%s\", &hdr, &err,\n " shortname;
6204 pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6207 pr " if (r == -1) {\n";
6208 pr " guestfs___end_busy (g);\n";
6209 pr " return %s;\n" error_code;
6213 pr " if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6214 (String.uppercase shortname);
6215 pr " guestfs___end_busy (g);\n";
6216 pr " return %s;\n" error_code;
6220 pr " if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6221 pr " error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6222 pr " free (err.error_message);\n";
6223 pr " guestfs___end_busy (g);\n";
6224 pr " return %s;\n" error_code;
6228 (* Expecting to receive further files (FileOut)? *)
6232 pr " if (guestfs___recv_file (g, %s) == -1) {\n" n;
6233 pr " guestfs___end_busy (g);\n";
6234 pr " return %s;\n" error_code;
6240 pr " guestfs___end_busy (g);\n";
6242 (match fst style with
6243 | RErr -> pr " return 0;\n"
6244 | RInt n | RInt64 n | RBool n ->
6245 pr " return ret.%s;\n" n
6246 | RConstString _ | RConstOptString _ ->
6247 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6249 pr " return ret.%s; /* caller will free */\n" n
6250 | RStringList n | RHashtable n ->
6251 pr " /* caller will free this, but we need to add a NULL entry */\n";
6252 pr " ret.%s.%s_val =\n" n n;
6253 pr " safe_realloc (g, ret.%s.%s_val,\n" n n;
6254 pr " sizeof (char *) * (ret.%s.%s_len + 1));\n"
6256 pr " ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6257 pr " return ret.%s.%s_val;\n" n n
6259 pr " /* caller will free this */\n";
6260 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6261 | RStructList (n, _) ->
6262 pr " /* caller will free this */\n";
6263 pr " return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6265 pr " /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6266 pr " * _val might be NULL here. To make the API saner for\n";
6267 pr " * callers, we turn this case into a unique pointer (using\n";
6268 pr " * malloc(1)).\n";
6270 pr " if (ret.%s.%s_len > 0) {\n" n n;
6271 pr " *size_r = ret.%s.%s_len;\n" n n;
6272 pr " return ret.%s.%s_val; /* caller will free */\n" n n;
6274 pr " free (ret.%s.%s_val);\n" n n;
6275 pr " char *p = safe_malloc (g, 1);\n";
6276 pr " *size_r = ret.%s.%s_len;\n" n n;
6284 (* Functions to free structures. *)
6285 pr "/* Structure-freeing functions. These rely on the fact that the\n";
6286 pr " * structure format is identical to the XDR format. See note in\n";
6287 pr " * generator.ml.\n";
6294 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6296 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6302 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6304 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6311 (* Generate daemon/actions.h. *)
6312 and generate_daemon_actions_h () =
6313 generate_header CStyle GPLv2plus;
6315 pr "#include \"../src/guestfs_protocol.h\"\n";
6319 fun (name, style, _, _, _, _, _) ->
6321 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6325 (* Generate the linker script which controls the visibility of
6326 * symbols in the public ABI and ensures no other symbols get
6327 * exported accidentally.
6329 and generate_linker_script () =
6330 generate_header HashStyle GPLv2plus;
6335 "guestfs_get_error_handler";
6336 "guestfs_get_out_of_memory_handler";
6337 "guestfs_last_error";
6338 "guestfs_set_close_callback";
6339 "guestfs_set_error_handler";
6340 "guestfs_set_launch_done_callback";
6341 "guestfs_set_log_message_callback";
6342 "guestfs_set_out_of_memory_handler";
6343 "guestfs_set_subprocess_quit_callback";
6345 (* Unofficial parts of the API: the bindings code use these
6346 * functions, so it is useful to export them.
6348 "guestfs_safe_calloc";
6349 "guestfs_safe_malloc";
6350 "guestfs_safe_strdup";
6351 "guestfs_safe_memdup";
6354 List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6358 List.map (fun (typ, _) ->
6359 ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6362 let globals = List.sort compare (globals @ functions @ structs) in
6366 List.iter (pr " %s;\n") globals;
6373 (* Generate the server-side stubs. *)
6374 and generate_daemon_actions () =
6375 generate_header CStyle GPLv2plus;
6377 pr "#include <config.h>\n";
6379 pr "#include <stdio.h>\n";
6380 pr "#include <stdlib.h>\n";
6381 pr "#include <string.h>\n";
6382 pr "#include <inttypes.h>\n";
6383 pr "#include <rpc/types.h>\n";
6384 pr "#include <rpc/xdr.h>\n";
6386 pr "#include \"daemon.h\"\n";
6387 pr "#include \"c-ctype.h\"\n";
6388 pr "#include \"../src/guestfs_protocol.h\"\n";
6389 pr "#include \"actions.h\"\n";
6393 fun (name, style, _, _, _, _, _) ->
6394 (* Generate server-side stubs. *)
6395 pr "static void %s_stub (XDR *xdr_in)\n" name;
6398 match fst style with
6399 | RErr | RInt _ -> pr " int r;\n"; "-1"
6400 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6401 | RBool _ -> pr " int r;\n"; "-1"
6402 | RConstString _ | RConstOptString _ ->
6403 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6404 | RString _ -> pr " char *r;\n"; "NULL"
6405 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
6406 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
6407 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
6409 pr " size_t size = 1;\n";
6413 (match snd style with
6416 pr " struct guestfs_%s_args args;\n" name;
6419 | Device n | Dev_or_Path n
6422 | OptString n -> pr " char *%s;\n" n
6423 | StringList n | DeviceList n -> pr " char **%s;\n" n
6424 | Bool n -> pr " int %s;\n" n
6425 | Int n -> pr " int %s;\n" n
6426 | Int64 n -> pr " int64_t %s;\n" n
6427 | FileIn _ | FileOut _ -> ()
6429 pr " const char *%s;\n" n;
6430 pr " size_t %s_size;\n" n
6436 List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6438 (match snd style with
6441 pr " memset (&args, 0, sizeof args);\n";
6443 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6445 pr " if (cancel_receive () != -2)\n";
6446 pr " reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6450 pr " char *%s = args.%s;\n" n n
6452 let pr_list_handling_code n =
6453 pr " %s = realloc (args.%s.%s_val,\n" n n n;
6454 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6455 pr " if (%s == NULL) {\n" n;
6457 pr " if (cancel_receive () != -2)\n";
6458 pr " reply_with_perror (\"realloc\");\n";
6461 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
6462 pr " args.%s.%s_val = %s;\n" n n n;
6468 pr " ABS_PATH (%s, %s, goto done);\n"
6469 n (if is_filein then "cancel_receive ()" else "0");
6472 pr " RESOLVE_DEVICE (%s, %s, goto done);\n"
6473 n (if is_filein then "cancel_receive ()" else "0");
6476 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6477 n (if is_filein then "cancel_receive ()" else "0");
6478 | String n -> pr_args n
6479 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
6481 pr_list_handling_code n;
6483 pr_list_handling_code n;
6484 pr " /* Ensure that each is a device,\n";
6485 pr " * and perform device name translation.\n";
6489 pr " for (i = 0; %s[i] != NULL; ++i)\n" n;
6490 pr " RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6491 (if is_filein then "cancel_receive ()" else "0");
6493 | Bool n -> pr " %s = args.%s;\n" n n
6494 | Int n -> pr " %s = args.%s;\n" n n
6495 | Int64 n -> pr " %s = args.%s;\n" n n
6496 | FileIn _ | FileOut _ -> ()
6498 pr " %s = args.%s.%s_val;\n" n n n;
6499 pr " %s_size = args.%s.%s_len;\n" n n n
6504 (* this is used at least for do_equal *)
6505 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6506 (* Emit NEED_ROOT just once, even when there are two or
6507 more Pathname args *)
6508 pr " NEED_ROOT (%s, goto done);\n"
6509 (if is_filein then "cancel_receive ()" else "0");
6512 (* Don't want to call the impl with any FileIn or FileOut
6513 * parameters, since these go "outside" the RPC protocol.
6516 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6518 pr " r = do_%s " name;
6519 generate_c_call_args (fst style, args');
6522 (match fst style with
6523 | RErr | RInt _ | RInt64 _ | RBool _
6524 | RConstString _ | RConstOptString _
6525 | RString _ | RStringList _ | RHashtable _
6526 | RStruct (_, _) | RStructList (_, _) ->
6527 pr " if (r == %s)\n" error_code;
6528 pr " /* do_%s has already called reply_with_error */\n" name;
6532 pr " /* size == 0 && r == NULL could be a non-error case (just\n";
6533 pr " * an ordinary zero-length buffer), so be careful ...\n";
6535 pr " if (size == 1 && r == %s)\n" error_code;
6536 pr " /* do_%s has already called reply_with_error */\n" name;
6541 (* If there are any FileOut parameters, then the impl must
6542 * send its own reply.
6545 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6547 pr " /* do_%s has already sent a reply */\n" name
6549 match fst style with
6550 | RErr -> pr " reply (NULL, NULL);\n"
6551 | RInt n | RInt64 n | RBool n ->
6552 pr " struct guestfs_%s_ret ret;\n" name;
6553 pr " ret.%s = r;\n" n;
6554 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6556 | RConstString _ | RConstOptString _ ->
6557 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6559 pr " struct guestfs_%s_ret ret;\n" name;
6560 pr " ret.%s = r;\n" n;
6561 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6564 | RStringList n | RHashtable n ->
6565 pr " struct guestfs_%s_ret ret;\n" name;
6566 pr " ret.%s.%s_len = count_strings (r);\n" n n;
6567 pr " ret.%s.%s_val = r;\n" n n;
6568 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6570 pr " free_strings (r);\n"
6572 pr " struct guestfs_%s_ret ret;\n" name;
6573 pr " ret.%s = *r;\n" n;
6574 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6576 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6578 | RStructList (n, _) ->
6579 pr " struct guestfs_%s_ret ret;\n" name;
6580 pr " ret.%s = *r;\n" n;
6581 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6583 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6586 pr " struct guestfs_%s_ret ret;\n" name;
6587 pr " ret.%s.%s_val = r;\n" n n;
6588 pr " ret.%s.%s_len = size;\n" n n;
6589 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6594 (* Free the args. *)
6596 (match snd style with
6599 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6606 (* Dispatch function. *)
6607 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6609 pr " switch (proc_nr) {\n";
6612 fun (name, style, _, _, _, _, _) ->
6613 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
6614 pr " %s_stub (xdr_in);\n" name;
6619 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";
6624 (* LVM columns and tokenization functions. *)
6625 (* XXX This generates crap code. We should rethink how we
6631 pr "static const char *lvm_%s_cols = \"%s\";\n"
6632 typ (String.concat "," (List.map fst cols));
6635 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6637 pr " char *tok, *p, *next;\n";
6638 pr " size_t i, j;\n";
6641 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6644 pr " if (!str) {\n";
6645 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6648 pr " if (!*str || c_isspace (*str)) {\n";
6649 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6654 fun (name, coltype) ->
6655 pr " if (!tok) {\n";
6656 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6659 pr " p = strchrnul (tok, ',');\n";
6660 pr " if (*p) next = p+1; else next = NULL;\n";
6661 pr " *p = '\\0';\n";
6664 pr " r->%s = strdup (tok);\n" name;
6665 pr " if (r->%s == NULL) {\n" name;
6666 pr " perror (\"strdup\");\n";
6670 pr " for (i = j = 0; i < 32; ++j) {\n";
6671 pr " if (tok[j] == '\\0') {\n";
6672 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6674 pr " } else if (tok[j] != '-')\n";
6675 pr " r->%s[i++] = tok[j];\n" name;
6678 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6679 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6683 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6684 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6688 pr " if (tok[0] == '\\0')\n";
6689 pr " r->%s = -1;\n" name;
6690 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6691 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6694 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6695 assert false (* can never be an LVM column *)
6697 pr " tok = next;\n";
6700 pr " if (tok != NULL) {\n";
6701 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6708 pr "guestfs_int_lvm_%s_list *\n" typ;
6709 pr "parse_command_line_%ss (void)\n" typ;
6711 pr " char *out, *err;\n";
6712 pr " char *p, *pend;\n";
6714 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
6715 pr " void *newp;\n";
6717 pr " ret = malloc (sizeof *ret);\n";
6718 pr " if (!ret) {\n";
6719 pr " reply_with_perror (\"malloc\");\n";
6720 pr " return NULL;\n";
6723 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6724 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6726 pr " r = command (&out, &err,\n";
6727 pr " \"lvm\", \"%ss\",\n" typ;
6728 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6729 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6730 pr " if (r == -1) {\n";
6731 pr " reply_with_error (\"%%s\", err);\n";
6732 pr " free (out);\n";
6733 pr " free (err);\n";
6734 pr " free (ret);\n";
6735 pr " return NULL;\n";
6738 pr " free (err);\n";
6740 pr " /* Tokenize each line of the output. */\n";
6743 pr " while (p) {\n";
6744 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
6745 pr " if (pend) {\n";
6746 pr " *pend = '\\0';\n";
6750 pr " while (*p && c_isspace (*p)) /* Skip any leading whitespace. */\n";
6753 pr " if (!*p) { /* Empty line? Skip it. */\n";
6758 pr " /* Allocate some space to store this next entry. */\n";
6759 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6760 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6761 pr " if (newp == NULL) {\n";
6762 pr " reply_with_perror (\"realloc\");\n";
6763 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6764 pr " free (ret);\n";
6765 pr " free (out);\n";
6766 pr " return NULL;\n";
6768 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6770 pr " /* Tokenize the next entry. */\n";
6771 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6772 pr " if (r == -1) {\n";
6773 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6774 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6775 pr " free (ret);\n";
6776 pr " free (out);\n";
6777 pr " return NULL;\n";
6784 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6786 pr " free (out);\n";
6787 pr " return ret;\n";
6790 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6792 (* Generate a list of function names, for debugging in the daemon.. *)
6793 and generate_daemon_names () =
6794 generate_header CStyle GPLv2plus;
6796 pr "#include <config.h>\n";
6798 pr "#include \"daemon.h\"\n";
6801 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
6802 pr "const char *function_names[] = {\n";
6804 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
6808 (* Generate the optional groups for the daemon to implement
6809 * guestfs_available.
6811 and generate_daemon_optgroups_c () =
6812 generate_header CStyle GPLv2plus;
6814 pr "#include <config.h>\n";
6816 pr "#include \"daemon.h\"\n";
6817 pr "#include \"optgroups.h\"\n";
6820 pr "struct optgroup optgroups[] = {\n";
6823 pr " { \"%s\", optgroup_%s_available },\n" group group
6825 pr " { NULL, NULL }\n";
6828 and generate_daemon_optgroups_h () =
6829 generate_header CStyle GPLv2plus;
6833 pr "extern int optgroup_%s_available (void);\n" group
6836 (* Generate the tests. *)
6837 and generate_tests () =
6838 generate_header CStyle GPLv2plus;
6845 #include <sys/types.h>
6848 #include \"guestfs.h\"
6849 #include \"guestfs-internal.h\"
6851 static guestfs_h *g;
6852 static int suppress_error = 0;
6854 static void print_error (guestfs_h *g, void *data, const char *msg)
6856 if (!suppress_error)
6857 fprintf (stderr, \"%%s\\n\", msg);
6860 /* FIXME: nearly identical code appears in fish.c */
6861 static void print_strings (char *const *argv)
6865 for (argc = 0; argv[argc] != NULL; ++argc)
6866 printf (\"\\t%%s\\n\", argv[argc]);
6870 static void print_table (char const *const *argv)
6874 for (i = 0; argv[i] != NULL; i += 2)
6875 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6880 is_available (const char *group)
6882 const char *groups[] = { group, NULL };
6886 r = guestfs_available (g, (char **) groups);
6893 incr (guestfs_h *g, void *iv)
6895 int *i = (int *) iv;
6901 (* Generate a list of commands which are not tested anywhere. *)
6902 pr "static void no_test_warnings (void)\n";
6905 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6907 fun (_, _, _, _, tests, _, _) ->
6908 let tests = filter_map (
6910 | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6911 | (_, Disabled, _) -> None
6913 let seq = List.concat (List.map seq_of_test tests) in
6914 let cmds_tested = List.map List.hd seq in
6915 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6919 fun (name, _, _, _, _, _, _) ->
6920 if not (Hashtbl.mem hash name) then
6921 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6927 (* Generate the actual tests. Note that we generate the tests
6928 * in reverse order, deliberately, so that (in general) the
6929 * newest tests run first. This makes it quicker and easier to
6934 fun (name, _, _, flags, tests, _, _) ->
6935 mapi (generate_one_test name flags) tests
6936 ) (List.rev all_functions) in
6937 let test_names = List.concat test_names in
6938 let nr_tests = List.length test_names in
6941 int main (int argc, char *argv[])
6944 unsigned long int n_failed = 0;
6945 const char *filename;
6947 int nr_tests, test_num = 0;
6949 setbuf (stdout, NULL);
6951 no_test_warnings ();
6953 g = guestfs_create ();
6955 printf (\"guestfs_create FAILED\\n\");
6956 exit (EXIT_FAILURE);
6959 guestfs_set_error_handler (g, print_error, NULL);
6961 guestfs_set_path (g, \"../appliance\");
6963 filename = \"test1.img\";
6964 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6967 exit (EXIT_FAILURE);
6969 if (lseek (fd, %d, SEEK_SET) == -1) {
6973 exit (EXIT_FAILURE);
6975 if (write (fd, &c, 1) == -1) {
6979 exit (EXIT_FAILURE);
6981 if (close (fd) == -1) {
6984 exit (EXIT_FAILURE);
6986 if (guestfs_add_drive (g, filename) == -1) {
6987 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6988 exit (EXIT_FAILURE);
6991 filename = \"test2.img\";
6992 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6995 exit (EXIT_FAILURE);
6997 if (lseek (fd, %d, SEEK_SET) == -1) {
7001 exit (EXIT_FAILURE);
7003 if (write (fd, &c, 1) == -1) {
7007 exit (EXIT_FAILURE);
7009 if (close (fd) == -1) {
7012 exit (EXIT_FAILURE);
7014 if (guestfs_add_drive (g, filename) == -1) {
7015 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7016 exit (EXIT_FAILURE);
7019 filename = \"test3.img\";
7020 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7023 exit (EXIT_FAILURE);
7025 if (lseek (fd, %d, SEEK_SET) == -1) {
7029 exit (EXIT_FAILURE);
7031 if (write (fd, &c, 1) == -1) {
7035 exit (EXIT_FAILURE);
7037 if (close (fd) == -1) {
7040 exit (EXIT_FAILURE);
7042 if (guestfs_add_drive (g, filename) == -1) {
7043 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7044 exit (EXIT_FAILURE);
7047 if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7048 printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7049 exit (EXIT_FAILURE);
7052 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7055 if (guestfs_launch (g) == -1) {
7056 printf (\"guestfs_launch FAILED\\n\");
7057 exit (EXIT_FAILURE);
7060 /* Cancel previous alarm. */
7065 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7069 pr " test_num++;\n";
7070 pr " if (guestfs_get_verbose (g))\n";
7071 pr " printf (\"-------------------------------------------------------------------------------\\n\");\n";
7072 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7073 pr " if (%s () == -1) {\n" test_name;
7074 pr " printf (\"%s FAILED\\n\");\n" test_name;
7075 pr " n_failed++;\n";
7080 pr " /* Check close callback is called. */
7081 int close_sentinel = 1;
7082 guestfs_set_close_callback (g, incr, &close_sentinel);
7086 if (close_sentinel != 2) {
7087 fprintf (stderr, \"close callback was not called\\n\");
7088 exit (EXIT_FAILURE);
7091 unlink (\"test1.img\");
7092 unlink (\"test2.img\");
7093 unlink (\"test3.img\");
7097 pr " if (n_failed > 0) {\n";
7098 pr " printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7099 pr " exit (EXIT_FAILURE);\n";
7103 pr " exit (EXIT_SUCCESS);\n";
7106 and generate_one_test name flags i (init, prereq, test) =
7107 let test_name = sprintf "test_%s_%d" name i in
7110 static int %s_skip (void)
7114 str = getenv (\"TEST_ONLY\");
7116 return strstr (str, \"%s\") == NULL;
7117 str = getenv (\"SKIP_%s\");
7118 if (str && STREQ (str, \"1\")) return 1;
7119 str = getenv (\"SKIP_TEST_%s\");
7120 if (str && STREQ (str, \"1\")) return 1;
7124 " test_name name (String.uppercase test_name) (String.uppercase name);
7127 | Disabled | Always | IfAvailable _ -> ()
7128 | If code | Unless code ->
7129 pr "static int %s_prereq (void)\n" test_name;
7137 static int %s (void)
7140 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
7144 " test_name test_name test_name;
7146 (* Optional functions should only be tested if the relevant
7147 * support is available in the daemon.
7152 pr " if (!is_available (\"%s\")) {\n" group;
7153 pr " printf (\" %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7161 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7163 pr " if (! %s_prereq ()) {\n" test_name;
7164 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7168 generate_one_test_body name i test_name init test;
7170 pr " if (%s_prereq ()) {\n" test_name;
7171 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7175 generate_one_test_body name i test_name init test;
7176 | IfAvailable group ->
7177 pr " if (!is_available (\"%s\")) {\n" group;
7178 pr " printf (\" %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7182 generate_one_test_body name i test_name init test;
7184 generate_one_test_body name i test_name init test
7192 and generate_one_test_body name i test_name init test =
7194 | InitNone (* XXX at some point, InitNone and InitEmpty became
7195 * folded together as the same thing. Really we should
7196 * make InitNone do nothing at all, but the tests may
7197 * need to be checked to make sure this is OK.
7200 pr " /* InitNone|InitEmpty for %s */\n" test_name;
7201 List.iter (generate_test_command_call test_name)
7202 [["blockdev_setrw"; "/dev/sda"];
7206 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7207 List.iter (generate_test_command_call test_name)
7208 [["blockdev_setrw"; "/dev/sda"];
7211 ["part_disk"; "/dev/sda"; "mbr"]]
7213 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7214 List.iter (generate_test_command_call test_name)
7215 [["blockdev_setrw"; "/dev/sda"];
7218 ["part_disk"; "/dev/sda"; "mbr"];
7219 ["mkfs"; "ext2"; "/dev/sda1"];
7220 ["mount_options"; ""; "/dev/sda1"; "/"]]
7221 | InitBasicFSonLVM ->
7222 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7224 List.iter (generate_test_command_call test_name)
7225 [["blockdev_setrw"; "/dev/sda"];
7228 ["part_disk"; "/dev/sda"; "mbr"];
7229 ["pvcreate"; "/dev/sda1"];
7230 ["vgcreate"; "VG"; "/dev/sda1"];
7231 ["lvcreate"; "LV"; "VG"; "8"];
7232 ["mkfs"; "ext2"; "/dev/VG/LV"];
7233 ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7235 pr " /* InitISOFS for %s */\n" test_name;
7236 List.iter (generate_test_command_call test_name)
7237 [["blockdev_setrw"; "/dev/sda"];
7240 ["mount_ro"; "/dev/sdd"; "/"]]
7243 let get_seq_last = function
7245 failwithf "%s: you cannot use [] (empty list) when expecting a command"
7248 let seq = List.rev seq in
7249 List.rev (List.tl seq), List.hd seq
7254 pr " /* TestRun for %s (%d) */\n" name i;
7255 List.iter (generate_test_command_call test_name) seq
7256 | TestOutput (seq, expected) ->
7257 pr " /* TestOutput for %s (%d) */\n" name i;
7258 pr " const char *expected = \"%s\";\n" (c_quote expected);
7259 let seq, last = get_seq_last seq in
7261 pr " if (STRNEQ (r, expected)) {\n";
7262 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7266 List.iter (generate_test_command_call test_name) seq;
7267 generate_test_command_call ~test test_name last
7268 | TestOutputList (seq, expected) ->
7269 pr " /* TestOutputList for %s (%d) */\n" name i;
7270 let seq, last = get_seq_last seq in
7274 pr " if (!r[%d]) {\n" i;
7275 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7276 pr " print_strings (r);\n";
7280 pr " const char *expected = \"%s\";\n" (c_quote str);
7281 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7282 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7287 pr " if (r[%d] != NULL) {\n" (List.length expected);
7288 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7290 pr " print_strings (r);\n";
7294 List.iter (generate_test_command_call test_name) seq;
7295 generate_test_command_call ~test test_name last
7296 | TestOutputListOfDevices (seq, expected) ->
7297 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
7298 let seq, last = get_seq_last seq in
7302 pr " if (!r[%d]) {\n" i;
7303 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7304 pr " print_strings (r);\n";
7308 pr " const char *expected = \"%s\";\n" (c_quote str);
7309 pr " r[%d][5] = 's';\n" i;
7310 pr " if (STRNEQ (r[%d], expected)) {\n" i;
7311 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7316 pr " if (r[%d] != NULL) {\n" (List.length expected);
7317 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7319 pr " print_strings (r);\n";
7323 List.iter (generate_test_command_call test_name) seq;
7324 generate_test_command_call ~test test_name last
7325 | TestOutputInt (seq, expected) ->
7326 pr " /* TestOutputInt for %s (%d) */\n" name i;
7327 let seq, last = get_seq_last seq in
7329 pr " if (r != %d) {\n" expected;
7330 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7336 List.iter (generate_test_command_call test_name) seq;
7337 generate_test_command_call ~test test_name last
7338 | TestOutputIntOp (seq, op, expected) ->
7339 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
7340 let seq, last = get_seq_last seq in
7342 pr " if (! (r %s %d)) {\n" op expected;
7343 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7344 test_name op expected;
7349 List.iter (generate_test_command_call test_name) seq;
7350 generate_test_command_call ~test test_name last
7351 | TestOutputTrue seq ->
7352 pr " /* TestOutputTrue for %s (%d) */\n" name i;
7353 let seq, last = get_seq_last seq in
7356 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7361 List.iter (generate_test_command_call test_name) seq;
7362 generate_test_command_call ~test test_name last
7363 | TestOutputFalse seq ->
7364 pr " /* TestOutputFalse for %s (%d) */\n" name i;
7365 let seq, last = get_seq_last seq in
7368 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7373 List.iter (generate_test_command_call test_name) seq;
7374 generate_test_command_call ~test test_name last
7375 | TestOutputLength (seq, expected) ->
7376 pr " /* TestOutputLength for %s (%d) */\n" name i;
7377 let seq, last = get_seq_last seq in
7380 pr " for (j = 0; j < %d; ++j)\n" expected;
7381 pr " if (r[j] == NULL) {\n";
7382 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
7384 pr " print_strings (r);\n";
7387 pr " if (r[j] != NULL) {\n";
7388 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
7390 pr " print_strings (r);\n";
7394 List.iter (generate_test_command_call test_name) seq;
7395 generate_test_command_call ~test test_name last
7396 | TestOutputBuffer (seq, expected) ->
7397 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
7398 pr " const char *expected = \"%s\";\n" (c_quote expected);
7399 let seq, last = get_seq_last seq in
7400 let len = String.length expected in
7402 pr " if (size != %d) {\n" len;
7403 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7406 pr " if (STRNEQLEN (r, expected, size)) {\n";
7407 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7411 List.iter (generate_test_command_call test_name) seq;
7412 generate_test_command_call ~test test_name last
7413 | TestOutputStruct (seq, checks) ->
7414 pr " /* TestOutputStruct for %s (%d) */\n" name i;
7415 let seq, last = get_seq_last seq in
7419 | CompareWithInt (field, expected) ->
7420 pr " if (r->%s != %d) {\n" field expected;
7421 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7422 test_name field expected;
7423 pr " (int) r->%s);\n" field;
7426 | CompareWithIntOp (field, op, expected) ->
7427 pr " if (!(r->%s %s %d)) {\n" field op expected;
7428 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7429 test_name field op expected;
7430 pr " (int) r->%s);\n" field;
7433 | CompareWithString (field, expected) ->
7434 pr " if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7435 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7436 test_name field expected;
7437 pr " r->%s);\n" field;
7440 | CompareFieldsIntEq (field1, field2) ->
7441 pr " if (r->%s != r->%s) {\n" field1 field2;
7442 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7443 test_name field1 field2;
7444 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
7447 | CompareFieldsStrEq (field1, field2) ->
7448 pr " if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7449 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7450 test_name field1 field2;
7451 pr " r->%s, r->%s);\n" field1 field2;
7456 List.iter (generate_test_command_call test_name) seq;
7457 generate_test_command_call ~test test_name last
7458 | TestLastFail seq ->
7459 pr " /* TestLastFail for %s (%d) */\n" name i;
7460 let seq, last = get_seq_last seq in
7461 List.iter (generate_test_command_call test_name) seq;
7462 generate_test_command_call test_name ~expect_error:true last
7464 (* Generate the code to run a command, leaving the result in 'r'.
7465 * If you expect to get an error then you should set expect_error:true.
7467 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7469 | [] -> assert false
7471 (* Look up the command to find out what args/ret it has. *)
7474 let _, style, _, _, _, _, _ =
7475 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7478 failwithf "%s: in test, command %s was not found" test_name name in
7480 if List.length (snd style) <> List.length args then
7481 failwithf "%s: in test, wrong number of args given to %s"
7488 | OptString n, "NULL" -> ()
7491 | Dev_or_Path n, arg
7493 | OptString n, arg ->
7494 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7495 | BufferIn n, arg ->
7496 pr " const char *%s = \"%s\";\n" n (c_quote arg);
7497 pr " size_t %s_size = %d;\n" n (String.length arg)
7501 | FileIn _, _ | FileOut _, _ -> ()
7502 | StringList n, "" | DeviceList n, "" ->
7503 pr " const char *const %s[1] = { NULL };\n" n
7504 | StringList n, arg | DeviceList n, arg ->
7505 let strs = string_split " " arg in
7508 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
7510 pr " const char *const %s[] = {\n" n;
7512 fun i _ -> pr " %s_%d,\n" n i
7516 ) (List.combine (snd style) args);
7519 match fst style with
7520 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7521 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7522 | RConstString _ | RConstOptString _ ->
7523 pr " const char *r;\n"; "NULL"
7524 | RString _ -> pr " char *r;\n"; "NULL"
7525 | RStringList _ | RHashtable _ ->
7529 | RStruct (_, typ) ->
7530 pr " struct guestfs_%s *r;\n" typ; "NULL"
7531 | RStructList (_, typ) ->
7532 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7535 pr " size_t size;\n";
7538 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
7539 pr " r = guestfs_%s (g" name;
7541 (* Generate the parameters. *)
7544 | OptString _, "NULL" -> pr ", NULL"
7546 | Device n, _ | Dev_or_Path n, _
7551 pr ", %s, %s_size" n n
7552 | FileIn _, arg | FileOut _, arg ->
7553 pr ", \"%s\"" (c_quote arg)
7554 | StringList n, _ | DeviceList n, _ ->
7555 pr ", (char **) %s" n
7558 try int_of_string arg
7559 with Failure "int_of_string" ->
7560 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7564 try Int64.of_string arg
7565 with Failure "int_of_string" ->
7566 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7569 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7570 ) (List.combine (snd style) args);
7572 (match fst style with
7573 | RBufferOut _ -> pr ", &size"
7579 if not expect_error then
7580 pr " if (r == %s)\n" error_code
7582 pr " if (r != %s)\n" error_code;
7585 (* Insert the test code. *)
7591 (match fst style with
7592 | RErr | RInt _ | RInt64 _ | RBool _
7593 | RConstString _ | RConstOptString _ -> ()
7594 | RString _ | RBufferOut _ -> pr " free (r);\n"
7595 | RStringList _ | RHashtable _ ->
7596 pr " for (i = 0; r[i] != NULL; ++i)\n";
7597 pr " free (r[i]);\n";
7599 | RStruct (_, typ) ->
7600 pr " guestfs_free_%s (r);\n" typ
7601 | RStructList (_, typ) ->
7602 pr " guestfs_free_%s_list (r);\n" typ
7608 let str = replace_str str "\r" "\\r" in
7609 let str = replace_str str "\n" "\\n" in
7610 let str = replace_str str "\t" "\\t" in
7611 let str = replace_str str "\000" "\\0" in
7614 (* Generate a lot of different functions for guestfish. *)
7615 and generate_fish_cmds () =
7616 generate_header CStyle GPLv2plus;
7620 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7622 let all_functions_sorted =
7624 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7625 ) all_functions_sorted in
7627 pr "#include <config.h>\n";
7629 pr "#include <stdio.h>\n";
7630 pr "#include <stdlib.h>\n";
7631 pr "#include <string.h>\n";
7632 pr "#include <inttypes.h>\n";
7634 pr "#include <guestfs.h>\n";
7635 pr "#include \"c-ctype.h\"\n";
7636 pr "#include \"full-write.h\"\n";
7637 pr "#include \"xstrtol.h\"\n";
7638 pr "#include \"fish.h\"\n";
7640 pr "/* Valid suffixes allowed for numbers. See Gnulib xstrtol function. */\n";
7641 pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7644 (* list_commands function, which implements guestfish -h *)
7645 pr "void list_commands (void)\n";
7647 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7648 pr " list_builtin_commands ();\n";
7650 fun (name, _, _, flags, _, shortdesc, _) ->
7651 let name = replace_char name '_' '-' in
7652 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7654 ) all_functions_sorted;
7655 pr " printf (\" %%s\\n\",";
7656 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7660 (* display_command function, which implements guestfish -h cmd *)
7661 pr "int display_command (const char *cmd)\n";
7664 fun (name, style, _, flags, _, shortdesc, longdesc) ->
7665 let name2 = replace_char name '_' '-' in
7667 try find_map (function FishAlias n -> Some n | _ -> None) flags
7668 with Not_found -> name in
7669 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7671 match snd style with
7675 name2 (String.concat " " (List.map name_of_argt args)) in
7678 if List.mem ProtocolLimitWarning flags then
7679 ("\n\n" ^ protocol_limit_warning)
7682 (* For DangerWillRobinson commands, we should probably have
7683 * guestfish prompt before allowing you to use them (especially
7684 * in interactive mode). XXX
7688 if List.mem DangerWillRobinson flags then
7689 ("\n\n" ^ danger_will_robinson)
7694 match deprecation_notice flags with
7696 | Some txt -> "\n\n" ^ txt in
7698 let describe_alias =
7699 if name <> alias then
7700 sprintf "\n\nYou can use '%s' as an alias for this command." alias
7704 pr "STRCASEEQ (cmd, \"%s\")" name;
7705 if name <> name2 then
7706 pr " || STRCASEEQ (cmd, \"%s\")" name2;
7707 if name <> alias then
7708 pr " || STRCASEEQ (cmd, \"%s\")" alias;
7710 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
7712 ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7713 "=head1 DESCRIPTION\n\n" ^
7714 longdesc ^ warnings ^ describe_alias);
7719 pr " return display_builtin_command (cmd);\n";
7723 let emit_print_list_function typ =
7724 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7727 pr " unsigned int i;\n";
7729 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
7730 pr " printf (\"[%%d] = {\\n\", i);\n";
7731 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
7732 pr " printf (\"}\\n\");\n";
7738 (* print_* functions *)
7742 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7744 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7747 pr " unsigned int i;\n";
7753 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7755 pr " printf (\"%%s%s: \", indent);\n" name;
7756 pr " for (i = 0; i < 32; ++i)\n";
7757 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7758 pr " printf (\"\\n\");\n"
7760 pr " printf (\"%%s%s: \", indent);\n" name;
7761 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7762 pr " if (c_isprint (%s->%s[i]))\n" typ name;
7763 pr " printf (\"%%c\", %s->%s[i]);\n" typ name;
7765 pr " printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7766 pr " printf (\"\\n\");\n"
7767 | name, (FUInt64|FBytes) ->
7768 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7771 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7774 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7777 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7780 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7782 | name, FOptPercent ->
7783 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7784 typ name name typ name;
7785 pr " else printf (\"%%s%s: \\n\", indent);\n" name
7791 (* Emit a print_TYPE_list function definition only if that function is used. *)
7794 | typ, (RStructListOnly | RStructAndList) ->
7795 (* generate the function for typ *)
7796 emit_print_list_function typ
7797 | typ, _ -> () (* empty *)
7798 ) (rstructs_used_by all_functions);
7800 (* Emit a print_TYPE function definition only if that function is used. *)
7803 | typ, (RStructOnly | RStructAndList) ->
7804 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7806 pr " print_%s_indent (%s, \"\");\n" typ typ;
7809 | typ, _ -> () (* empty *)
7810 ) (rstructs_used_by all_functions);
7812 (* run_<action> actions *)
7814 fun (name, style, _, flags, _, _, _) ->
7815 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7817 (match fst style with
7820 | RBool _ -> pr " int r;\n"
7821 | RInt64 _ -> pr " int64_t r;\n"
7822 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
7823 | RString _ -> pr " char *r;\n"
7824 | RStringList _ | RHashtable _ -> pr " char **r;\n"
7825 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
7826 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
7829 pr " size_t size;\n";
7835 | OptString n -> pr " const char *%s;\n" n
7839 | FileOut n -> pr " char *%s;\n" n
7841 pr " const char *%s;\n" n;
7842 pr " size_t %s_size;\n" n
7843 | StringList n | DeviceList n -> pr " char **%s;\n" n
7844 | Bool n -> pr " int %s;\n" n
7845 | Int n -> pr " int %s;\n" n
7846 | Int64 n -> pr " int64_t %s;\n" n
7849 (* Check and convert parameters. *)
7850 let argc_expected = List.length (snd style) in
7851 pr " if (argc != %d) {\n" argc_expected;
7852 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7854 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7858 let parse_integer fn fntyp rtyp range name i =
7860 pr " strtol_error xerr;\n";
7861 pr " %s r;\n" fntyp;
7863 pr " xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7864 pr " if (xerr != LONGINT_OK) {\n";
7865 pr " fprintf (stderr,\n";
7866 pr " _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7867 pr " cmd, \"%s\", \"%s\", xerr);\n" name fn;
7872 | Some (min, max, comment) ->
7873 pr " /* %s */\n" comment;
7874 pr " if (r < %s || r > %s) {\n" min max;
7875 pr " fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7879 pr " /* The check above should ensure this assignment does not overflow. */\n";
7881 pr " %s = r;\n" name;
7890 pr " %s = argv[%d];\n" name i
7892 | Dev_or_Path name ->
7893 pr " %s = resolve_win_path (argv[%d]);\n" name i;
7894 pr " if (%s == NULL) return -1;\n" name
7896 pr " %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7899 pr " %s = argv[%d];\n" name i;
7900 pr " %s_size = strlen (argv[%d]);\n" name i
7902 pr " %s = file_in (argv[%d]);\n" name i;
7903 pr " if (%s == NULL) return -1;\n" name
7905 pr " %s = file_out (argv[%d]);\n" name i;
7906 pr " if (%s == NULL) return -1;\n" name
7907 | StringList name | DeviceList name ->
7908 pr " %s = parse_string_list (argv[%d]);\n" name i;
7909 pr " if (%s == NULL) return -1;\n" name;
7911 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7914 let min = "(-(2LL<<30))"
7915 and max = "((2LL<<30)-1)"
7917 "The Int type in the generator is a signed 31 bit int." in
7918 Some (min, max, comment) in
7919 parse_integer "xstrtoll" "long long" "int" range name i
7921 parse_integer "xstrtoll" "long long" "int64_t" None name i
7924 (* Call C API function. *)
7925 pr " r = guestfs_%s " name;
7926 generate_c_call_args ~handle:"g" style;
7931 | Device _ | String _
7932 | OptString _ | Bool _
7935 | Pathname name | Dev_or_Path name | FileOut name ->
7936 pr " free (%s);\n" name
7938 pr " free_file_in (%s);\n" name
7939 | StringList name | DeviceList name ->
7940 pr " free_strings (%s);\n" name
7943 (* Any output flags? *)
7945 let flags = filter_map (
7946 function FishOutput flag -> Some flag | _ -> None
7952 failwithf "%s: more than one FishOutput flag is not allowed" name in
7954 (* Check return value for errors and display command results. *)
7955 (match fst style with
7956 | RErr -> pr " return r;\n"
7958 pr " if (r == -1) return -1;\n";
7959 (match fish_output with
7961 pr " printf (\"%%d\\n\", r);\n";
7962 | Some FishOutputOctal ->
7963 pr " printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7964 | Some FishOutputHexadecimal ->
7965 pr " printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7968 pr " if (r == -1) return -1;\n";
7969 (match fish_output with
7971 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
7972 | Some FishOutputOctal ->
7973 pr " printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7974 | Some FishOutputHexadecimal ->
7975 pr " printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7978 pr " if (r == -1) return -1;\n";
7979 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7982 pr " if (r == NULL) return -1;\n";
7983 pr " printf (\"%%s\\n\", r);\n";
7985 | RConstOptString _ ->
7986 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
7989 pr " if (r == NULL) return -1;\n";
7990 pr " printf (\"%%s\\n\", r);\n";
7994 pr " if (r == NULL) return -1;\n";
7995 pr " print_strings (r);\n";
7996 pr " free_strings (r);\n";
7998 | RStruct (_, typ) ->
7999 pr " if (r == NULL) return -1;\n";
8000 pr " print_%s (r);\n" typ;
8001 pr " guestfs_free_%s (r);\n" typ;
8003 | RStructList (_, typ) ->
8004 pr " if (r == NULL) return -1;\n";
8005 pr " print_%s_list (r);\n" typ;
8006 pr " guestfs_free_%s_list (r);\n" typ;
8009 pr " if (r == NULL) return -1;\n";
8010 pr " print_table (r);\n";
8011 pr " free_strings (r);\n";
8014 pr " if (r == NULL) return -1;\n";
8015 pr " if (full_write (1, r, size) != size) {\n";
8016 pr " perror (\"write\");\n";
8027 (* run_action function *)
8028 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8031 fun (name, _, _, flags, _, _, _) ->
8032 let name2 = replace_char name '_' '-' in
8034 try find_map (function FishAlias n -> Some n | _ -> None) flags
8035 with Not_found -> name in
8037 pr "STRCASEEQ (cmd, \"%s\")" name;
8038 if name <> name2 then
8039 pr " || STRCASEEQ (cmd, \"%s\")" name2;
8040 if name <> alias then
8041 pr " || STRCASEEQ (cmd, \"%s\")" alias;
8043 pr " return run_%s (cmd, argc, argv);\n" name;
8047 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8048 pr " if (command_num == 1)\n";
8049 pr " extended_help_message ();\n";
8056 (* Readline completion for guestfish. *)
8057 and generate_fish_completion () =
8058 generate_header CStyle GPLv2plus;
8062 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8072 #ifdef HAVE_LIBREADLINE
8073 #include <readline/readline.h>
8078 #ifdef HAVE_LIBREADLINE
8080 static const char *const commands[] = {
8081 BUILTIN_COMMANDS_FOR_COMPLETION,
8084 (* Get the commands, including the aliases. They don't need to be
8085 * sorted - the generator() function just does a dumb linear search.
8089 fun (name, _, _, flags, _, _, _) ->
8090 let name2 = replace_char name '_' '-' in
8092 try find_map (function FishAlias n -> Some n | _ -> None) flags
8093 with Not_found -> name in
8095 if name <> alias then [name2; alias] else [name2]
8097 let commands = List.flatten commands in
8099 List.iter (pr " \"%s\",\n") commands;
8105 generator (const char *text, int state)
8107 static size_t index, len;
8112 len = strlen (text);
8115 rl_attempted_completion_over = 1;
8117 while ((name = commands[index]) != NULL) {
8119 if (STRCASEEQLEN (name, text, len))
8120 return strdup (name);
8126 #endif /* HAVE_LIBREADLINE */
8128 #ifdef HAVE_RL_COMPLETION_MATCHES
8129 #define RL_COMPLETION_MATCHES rl_completion_matches
8131 #ifdef HAVE_COMPLETION_MATCHES
8132 #define RL_COMPLETION_MATCHES completion_matches
8134 #endif /* else just fail if we don't have either symbol */
8137 do_completion (const char *text, int start, int end)
8139 char **matches = NULL;
8141 #ifdef HAVE_LIBREADLINE
8142 rl_completion_append_character = ' ';
8145 matches = RL_COMPLETION_MATCHES (text, generator);
8146 else if (complete_dest_paths)
8147 matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8154 (* Generate the POD documentation for guestfish. *)
8155 and generate_fish_actions_pod () =
8156 let all_functions_sorted =
8158 fun (_, _, _, flags, _, _, _) ->
8159 not (List.mem NotInFish flags || List.mem NotInDocs flags)
8160 ) all_functions_sorted in
8162 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8165 fun (name, style, _, flags, _, _, longdesc) ->
8167 Str.global_substitute rex (
8170 try Str.matched_group 1 s
8172 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8173 "C<" ^ replace_char sub '_' '-' ^ ">"
8175 let name = replace_char name '_' '-' in
8177 try find_map (function FishAlias n -> Some n | _ -> None) flags
8178 with Not_found -> name in
8180 pr "=head2 %s" name;
8181 if name <> alias then
8188 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8189 | OptString n -> pr " %s" n
8190 | StringList n | DeviceList n -> pr " '%s ...'" n
8191 | Bool _ -> pr " true|false"
8192 | Int n -> pr " %s" n
8193 | Int64 n -> pr " %s" n
8194 | FileIn n | FileOut n -> pr " (%s|-)" n
8195 | BufferIn n -> pr " %s" n
8199 pr "%s\n\n" longdesc;
8201 if List.exists (function FileIn _ | FileOut _ -> true
8202 | _ -> false) (snd style) then
8203 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8205 if List.mem ProtocolLimitWarning flags then
8206 pr "%s\n\n" protocol_limit_warning;
8208 if List.mem DangerWillRobinson flags then
8209 pr "%s\n\n" danger_will_robinson;
8211 match deprecation_notice flags with
8213 | Some txt -> pr "%s\n\n" txt
8214 ) all_functions_sorted
8216 (* Generate a C function prototype. *)
8217 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8218 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8220 ?handle name style =
8221 if extern then pr "extern ";
8222 if static then pr "static ";
8223 (match fst style with
8225 | RInt _ -> pr "int "
8226 | RInt64 _ -> pr "int64_t "
8227 | RBool _ -> pr "int "
8228 | RConstString _ | RConstOptString _ -> pr "const char *"
8229 | RString _ | RBufferOut _ -> pr "char *"
8230 | RStringList _ | RHashtable _ -> pr "char **"
8231 | RStruct (_, typ) ->
8232 if not in_daemon then pr "struct guestfs_%s *" typ
8233 else pr "guestfs_int_%s *" typ
8234 | RStructList (_, typ) ->
8235 if not in_daemon then pr "struct guestfs_%s_list *" typ
8236 else pr "guestfs_int_%s_list *" typ
8238 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8239 pr "%s%s (" prefix name;
8240 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8243 let comma = ref false in
8246 | Some handle -> pr "guestfs_h *%s" handle; comma := true
8250 if single_line then pr ", " else pr ",\n\t\t"
8257 | Device n | Dev_or_Path n
8261 pr "const char *%s" n
8262 | StringList n | DeviceList n ->
8264 pr "char *const *%s" n
8265 | Bool n -> next (); pr "int %s" n
8266 | Int n -> next (); pr "int %s" n
8267 | Int64 n -> next (); pr "int64_t %s" n
8270 if not in_daemon then (next (); pr "const char *%s" n)
8273 pr "const char *%s" n;
8275 pr "size_t %s_size" n
8277 if is_RBufferOut then (next (); pr "size_t *size_r");
8280 if semicolon then pr ";";
8281 if newline then pr "\n"
8283 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8284 and generate_c_call_args ?handle ?(decl = false) style =
8286 let comma = ref false in
8288 if !comma then pr ", ";
8293 | Some handle -> pr "%s" handle; comma := true
8299 pr "%s, %s_size" n n
8302 pr "%s" (name_of_argt arg)
8304 (* For RBufferOut calls, add implicit &size parameter. *)
8306 match fst style with
8314 (* Generate the OCaml bindings interface. *)
8315 and generate_ocaml_mli () =
8316 generate_header OCamlStyle LGPLv2plus;
8319 (** For API documentation you should refer to the C API
8320 in the guestfs(3) manual page. The OCaml API uses almost
8321 exactly the same calls. *)
8324 (** A [guestfs_h] handle. *)
8326 exception Error of string
8327 (** This exception is raised when there is an error. *)
8329 exception Handle_closed of string
8330 (** This exception is raised if you use a {!Guestfs.t} handle
8331 after calling {!close} on it. The string is the name of
8334 val create : unit -> t
8335 (** Create a {!Guestfs.t} handle. *)
8337 val close : t -> unit
8338 (** Close the {!Guestfs.t} handle and free up all resources used
8341 Handles are closed by the garbage collector when they become
8342 unreferenced, but callers can call this in order to provide
8343 predictable cleanup. *)
8346 generate_ocaml_structure_decls ();
8350 fun (name, style, _, _, _, shortdesc, _) ->
8351 generate_ocaml_prototype name style;
8352 pr "(** %s *)\n" shortdesc;
8354 ) all_functions_sorted
8356 (* Generate the OCaml bindings implementation. *)
8357 and generate_ocaml_ml () =
8358 generate_header OCamlStyle LGPLv2plus;
8363 exception Error of string
8364 exception Handle_closed of string
8366 external create : unit -> t = \"ocaml_guestfs_create\"
8367 external close : t -> unit = \"ocaml_guestfs_close\"
8369 (* Give the exceptions names, so they can be raised from the C code. *)
8371 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8372 Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8376 generate_ocaml_structure_decls ();
8380 fun (name, style, _, _, _, shortdesc, _) ->
8381 generate_ocaml_prototype ~is_external:true name style;
8382 ) all_functions_sorted
8384 (* Generate the OCaml bindings C implementation. *)
8385 and generate_ocaml_c () =
8386 generate_header CStyle LGPLv2plus;
8393 #include <caml/config.h>
8394 #include <caml/alloc.h>
8395 #include <caml/callback.h>
8396 #include <caml/fail.h>
8397 #include <caml/memory.h>
8398 #include <caml/mlvalues.h>
8399 #include <caml/signals.h>
8401 #include \"guestfs.h\"
8403 #include \"guestfs_c.h\"
8405 /* Copy a hashtable of string pairs into an assoc-list. We return
8406 * the list in reverse order, but hashtables aren't supposed to be
8409 static CAMLprim value
8410 copy_table (char * const * argv)
8413 CAMLlocal5 (rv, pairv, kv, vv, cons);
8417 for (i = 0; argv[i] != NULL; i += 2) {
8418 kv = caml_copy_string (argv[i]);
8419 vv = caml_copy_string (argv[i+1]);
8420 pairv = caml_alloc (2, 0);
8421 Store_field (pairv, 0, kv);
8422 Store_field (pairv, 1, vv);
8423 cons = caml_alloc (2, 0);
8424 Store_field (cons, 1, rv);
8426 Store_field (cons, 0, pairv);
8434 (* Struct copy functions. *)
8436 let emit_ocaml_copy_list_function typ =
8437 pr "static CAMLprim value\n";
8438 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8440 pr " CAMLparam0 ();\n";
8441 pr " CAMLlocal2 (rv, v);\n";
8442 pr " unsigned int i;\n";
8444 pr " if (%ss->len == 0)\n" typ;
8445 pr " CAMLreturn (Atom (0));\n";
8447 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
8448 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
8449 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
8450 pr " caml_modify (&Field (rv, i), v);\n";
8452 pr " CAMLreturn (rv);\n";
8460 let has_optpercent_col =
8461 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8463 pr "static CAMLprim value\n";
8464 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8466 pr " CAMLparam0 ();\n";
8467 if has_optpercent_col then
8468 pr " CAMLlocal3 (rv, v, v2);\n"
8470 pr " CAMLlocal2 (rv, v);\n";
8472 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
8477 pr " v = caml_copy_string (%s->%s);\n" typ name
8479 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
8480 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8483 pr " v = caml_alloc_string (32);\n";
8484 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
8485 | name, (FBytes|FInt64|FUInt64) ->
8486 pr " v = caml_copy_int64 (%s->%s);\n" typ name
8487 | name, (FInt32|FUInt32) ->
8488 pr " v = caml_copy_int32 (%s->%s);\n" typ name
8489 | name, FOptPercent ->
8490 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8491 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
8492 pr " v = caml_alloc (1, 0);\n";
8493 pr " Store_field (v, 0, v2);\n";
8494 pr " } else /* None */\n";
8495 pr " v = Val_int (0);\n";
8497 pr " v = Val_int (%s->%s);\n" typ name
8499 pr " Store_field (rv, %d, v);\n" i
8501 pr " CAMLreturn (rv);\n";
8506 (* Emit a copy_TYPE_list function definition only if that function is used. *)
8509 | typ, (RStructListOnly | RStructAndList) ->
8510 (* generate the function for typ *)
8511 emit_ocaml_copy_list_function typ
8512 | typ, _ -> () (* empty *)
8513 ) (rstructs_used_by all_functions);
8517 fun (name, style, _, _, _, _, _) ->
8518 pr "/* Automatically generated wrapper for function\n";
8520 generate_ocaml_prototype name style;
8525 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8527 let needs_extra_vs =
8528 match fst style with RConstOptString _ -> true | _ -> false in
8530 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8531 pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8532 List.iter (pr ", value %s") (List.tl params); pr ");\n";
8535 pr "CAMLprim value\n";
8536 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8537 List.iter (pr ", value %s") (List.tl params);
8542 | [p1; p2; p3; p4; p5] ->
8543 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
8544 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8545 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8546 pr " CAMLxparam%d (%s);\n"
8547 (List.length rest) (String.concat ", " rest)
8549 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8551 if not needs_extra_vs then
8552 pr " CAMLlocal1 (rv);\n"
8554 pr " CAMLlocal3 (rv, v, v2);\n";
8557 pr " guestfs_h *g = Guestfs_val (gv);\n";
8558 pr " if (g == NULL)\n";
8559 pr " ocaml_guestfs_raise_closed (\"%s\");\n" name;
8565 | Device n | Dev_or_Path n
8569 (* Copy strings in case the GC moves them: RHBZ#604691 *)
8570 pr " char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8572 pr " char *%s =\n" n;
8573 pr " %sv != Val_int (0) ?" n;
8574 pr " guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8576 pr " size_t %s_size = caml_string_length (%sv);\n" n n;
8577 pr " char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8578 | StringList n | DeviceList n ->
8579 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8581 pr " int %s = Bool_val (%sv);\n" n n
8583 pr " int %s = Int_val (%sv);\n" n n
8585 pr " int64_t %s = Int64_val (%sv);\n" n n
8588 match fst style with
8589 | RErr -> pr " int r;\n"; "-1"
8590 | RInt _ -> pr " int r;\n"; "-1"
8591 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8592 | RBool _ -> pr " int r;\n"; "-1"
8593 | RConstString _ | RConstOptString _ ->
8594 pr " const char *r;\n"; "NULL"
8595 | RString _ -> pr " char *r;\n"; "NULL"
8600 | RStruct (_, typ) ->
8601 pr " struct guestfs_%s *r;\n" typ; "NULL"
8602 | RStructList (_, typ) ->
8603 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8610 pr " size_t size;\n";
8614 pr " caml_enter_blocking_section ();\n";
8615 pr " r = guestfs_%s " name;
8616 generate_c_call_args ~handle:"g" style;
8618 pr " caml_leave_blocking_section ();\n";
8620 (* Free strings if we copied them above. *)
8623 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8624 | FileIn n | FileOut n | BufferIn n ->
8625 pr " free (%s);\n" n
8626 | StringList n | DeviceList n ->
8627 pr " ocaml_guestfs_free_strings (%s);\n" n;
8628 | Bool _ | Int _ | Int64 _ -> ()
8631 pr " if (r == %s)\n" error_code;
8632 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8635 (match fst style with
8636 | RErr -> pr " rv = Val_unit;\n"
8637 | RInt _ -> pr " rv = Val_int (r);\n"
8639 pr " rv = caml_copy_int64 (r);\n"
8640 | RBool _ -> pr " rv = Val_bool (r);\n"
8642 pr " rv = caml_copy_string (r);\n"
8643 | RConstOptString _ ->
8644 pr " if (r) { /* Some string */\n";
8645 pr " v = caml_alloc (1, 0);\n";
8646 pr " v2 = caml_copy_string (r);\n";
8647 pr " Store_field (v, 0, v2);\n";
8648 pr " } else /* None */\n";
8649 pr " v = Val_int (0);\n";
8651 pr " rv = caml_copy_string (r);\n";
8654 pr " rv = caml_copy_string_array ((const char **) r);\n";
8655 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8657 | RStruct (_, typ) ->
8658 pr " rv = copy_%s (r);\n" typ;
8659 pr " guestfs_free_%s (r);\n" typ;
8660 | RStructList (_, typ) ->
8661 pr " rv = copy_%s_list (r);\n" typ;
8662 pr " guestfs_free_%s_list (r);\n" typ;
8664 pr " rv = copy_table (r);\n";
8665 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8668 pr " rv = caml_alloc_string (size);\n";
8669 pr " memcpy (String_val (rv), r, size);\n";
8672 pr " CAMLreturn (rv);\n";
8676 if List.length params > 5 then (
8677 pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8678 pr "CAMLprim value ";
8679 pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8680 pr "CAMLprim value\n";
8681 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8683 pr " return ocaml_guestfs_%s (argv[0]" name;
8684 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8689 ) all_functions_sorted
8691 and generate_ocaml_structure_decls () =
8694 pr "type %s = {\n" typ;
8697 | name, FString -> pr " %s : string;\n" name
8698 | name, FBuffer -> pr " %s : string;\n" name
8699 | name, FUUID -> pr " %s : string;\n" name
8700 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
8701 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
8702 | name, FChar -> pr " %s : char;\n" name
8703 | name, FOptPercent -> pr " %s : float option;\n" name
8709 and generate_ocaml_prototype ?(is_external = false) name style =
8710 if is_external then pr "external " else pr "val ";
8711 pr "%s : t -> " name;
8714 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8715 | BufferIn _ -> pr "string -> "
8716 | OptString _ -> pr "string option -> "
8717 | StringList _ | DeviceList _ -> pr "string array -> "
8718 | Bool _ -> pr "bool -> "
8719 | Int _ -> pr "int -> "
8720 | Int64 _ -> pr "int64 -> "
8722 (match fst style with
8723 | RErr -> pr "unit" (* all errors are turned into exceptions *)
8724 | RInt _ -> pr "int"
8725 | RInt64 _ -> pr "int64"
8726 | RBool _ -> pr "bool"
8727 | RConstString _ -> pr "string"
8728 | RConstOptString _ -> pr "string option"
8729 | RString _ | RBufferOut _ -> pr "string"
8730 | RStringList _ -> pr "string array"
8731 | RStruct (_, typ) -> pr "%s" typ
8732 | RStructList (_, typ) -> pr "%s array" typ
8733 | RHashtable _ -> pr "(string * string) list"
8735 if is_external then (
8737 if List.length (snd style) + 1 > 5 then
8738 pr "\"ocaml_guestfs_%s_byte\" " name;
8739 pr "\"ocaml_guestfs_%s\"" name
8743 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8744 and generate_perl_xs () =
8745 generate_header CStyle LGPLv2plus;
8748 #include \"EXTERN.h\"
8752 #include <guestfs.h>
8755 #define PRId64 \"lld\"
8759 my_newSVll(long long val) {
8760 #ifdef USE_64_BIT_ALL
8761 return newSViv(val);
8765 len = snprintf(buf, 100, \"%%\" PRId64, val);
8766 return newSVpv(buf, len);
8771 #define PRIu64 \"llu\"
8775 my_newSVull(unsigned long long val) {
8776 #ifdef USE_64_BIT_ALL
8777 return newSVuv(val);
8781 len = snprintf(buf, 100, \"%%\" PRIu64, val);
8782 return newSVpv(buf, len);
8786 /* http://www.perlmonks.org/?node_id=680842 */
8788 XS_unpack_charPtrPtr (SV *arg) {
8793 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8794 croak (\"array reference expected\");
8796 av = (AV *)SvRV (arg);
8797 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8799 croak (\"malloc failed\");
8801 for (i = 0; i <= av_len (av); i++) {
8802 SV **elem = av_fetch (av, i, 0);
8804 if (!elem || !*elem)
8805 croak (\"missing element in list\");
8807 ret[i] = SvPV_nolen (*elem);
8815 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
8822 RETVAL = guestfs_create ();
8824 croak (\"could not create guestfs handle\");
8825 guestfs_set_error_handler (RETVAL, NULL, NULL);
8833 /* For the 'g' argument above we do the conversion explicitly and
8834 * don't rely on the typemap, because if the handle has been
8835 * explicitly closed we don't want the typemap conversion to
8838 HV *hv = (HV *) SvRV (sv);
8839 SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8841 guestfs_h *g = (guestfs_h *) SvIV (*svp);
8851 /* Avoid double-free in DESTROY method. */
8852 HV *hv = (HV *) SvRV (ST(0));
8853 (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8858 fun (name, style, _, _, _, _, _) ->
8859 (match fst style with
8860 | RErr -> pr "void\n"
8861 | RInt _ -> pr "SV *\n"
8862 | RInt64 _ -> pr "SV *\n"
8863 | RBool _ -> pr "SV *\n"
8864 | RConstString _ -> pr "SV *\n"
8865 | RConstOptString _ -> pr "SV *\n"
8866 | RString _ -> pr "SV *\n"
8867 | RBufferOut _ -> pr "SV *\n"
8869 | RStruct _ | RStructList _
8871 pr "void\n" (* all lists returned implictly on the stack *)
8873 (* Call and arguments. *)
8876 fun arg -> pr ", %s" (name_of_argt arg)
8879 pr " guestfs_h *g;\n";
8883 | Pathname n | Device n | Dev_or_Path n | String n
8884 | FileIn n | FileOut n ->
8887 pr " char *%s;\n" n;
8888 pr " size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8890 (* http://www.perlmonks.org/?node_id=554277
8891 * Note that the implicit handle argument means we have
8892 * to add 1 to the ST(x) operator.
8894 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8895 | StringList n | DeviceList n -> pr " char **%s;\n" n
8896 | Bool n -> pr " int %s;\n" n
8897 | Int n -> pr " int %s;\n" n
8898 | Int64 n -> pr " int64_t %s;\n" n
8901 let do_cleanups () =
8904 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8905 | Bool _ | Int _ | Int64 _
8906 | FileIn _ | FileOut _
8908 | StringList n | DeviceList n -> pr " free (%s);\n" n
8913 (match fst style with
8918 pr " r = guestfs_%s " name;
8919 generate_c_call_args ~handle:"g" style;
8922 pr " if (r == -1)\n";
8923 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8929 pr " %s = guestfs_%s " n name;
8930 generate_c_call_args ~handle:"g" style;
8933 pr " if (%s == -1)\n" n;
8934 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8935 pr " RETVAL = newSViv (%s);\n" n;
8940 pr " int64_t %s;\n" n;
8942 pr " %s = guestfs_%s " n name;
8943 generate_c_call_args ~handle:"g" style;
8946 pr " if (%s == -1)\n" n;
8947 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8948 pr " RETVAL = my_newSVll (%s);\n" n;
8953 pr " const char *%s;\n" n;
8955 pr " %s = guestfs_%s " n name;
8956 generate_c_call_args ~handle:"g" style;
8959 pr " if (%s == NULL)\n" n;
8960 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8961 pr " RETVAL = newSVpv (%s, 0);\n" n;
8964 | RConstOptString n ->
8966 pr " const char *%s;\n" n;
8968 pr " %s = guestfs_%s " n name;
8969 generate_c_call_args ~handle:"g" style;
8972 pr " if (%s == NULL)\n" n;
8973 pr " RETVAL = &PL_sv_undef;\n";
8975 pr " RETVAL = newSVpv (%s, 0);\n" n;
8980 pr " char *%s;\n" n;
8982 pr " %s = guestfs_%s " n name;
8983 generate_c_call_args ~handle:"g" style;
8986 pr " if (%s == NULL)\n" n;
8987 pr " croak (\"%%s\", guestfs_last_error (g));\n";
8988 pr " RETVAL = newSVpv (%s, 0);\n" n;
8989 pr " free (%s);\n" n;
8992 | RStringList n | RHashtable n ->
8994 pr " char **%s;\n" n;
8995 pr " size_t i, n;\n";
8997 pr " %s = guestfs_%s " n name;
8998 generate_c_call_args ~handle:"g" style;
9001 pr " if (%s == NULL)\n" n;
9002 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9003 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9004 pr " EXTEND (SP, n);\n";
9005 pr " for (i = 0; i < n; ++i) {\n";
9006 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9007 pr " free (%s[i]);\n" n;
9009 pr " free (%s);\n" n;
9010 | RStruct (n, typ) ->
9011 let cols = cols_of_struct typ in
9012 generate_perl_struct_code typ cols name style n do_cleanups
9013 | RStructList (n, typ) ->
9014 let cols = cols_of_struct typ in
9015 generate_perl_struct_list_code typ cols name style n do_cleanups
9018 pr " char *%s;\n" n;
9019 pr " size_t size;\n";
9021 pr " %s = guestfs_%s " n name;
9022 generate_c_call_args ~handle:"g" style;
9025 pr " if (%s == NULL)\n" n;
9026 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9027 pr " RETVAL = newSVpvn (%s, size);\n" n;
9028 pr " free (%s);\n" n;
9036 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9038 pr " struct guestfs_%s_list *%s;\n" typ n;
9042 pr " %s = guestfs_%s " n name;
9043 generate_c_call_args ~handle:"g" style;
9046 pr " if (%s == NULL)\n" n;
9047 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9048 pr " EXTEND (SP, %s->len);\n" n;
9049 pr " for (i = 0; i < %s->len; ++i) {\n" n;
9050 pr " hv = newHV ();\n";
9054 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9055 name (String.length name) n name
9057 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9058 name (String.length name) n name
9060 pr " (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9061 name (String.length name) n name n name
9062 | name, (FBytes|FUInt64) ->
9063 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9064 name (String.length name) n name
9066 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9067 name (String.length name) n name
9068 | name, (FInt32|FUInt32) ->
9069 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9070 name (String.length name) n name
9072 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9073 name (String.length name) n name
9074 | name, FOptPercent ->
9075 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9076 name (String.length name) n name
9078 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9080 pr " guestfs_free_%s_list (%s);\n" typ n
9082 and generate_perl_struct_code typ cols name style n do_cleanups =
9084 pr " struct guestfs_%s *%s;\n" typ n;
9086 pr " %s = guestfs_%s " n name;
9087 generate_c_call_args ~handle:"g" style;
9090 pr " if (%s == NULL)\n" n;
9091 pr " croak (\"%%s\", guestfs_last_error (g));\n";
9092 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
9094 fun ((name, _) as col) ->
9095 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9099 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9102 pr " PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9105 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9107 | name, (FBytes|FUInt64) ->
9108 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9111 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9113 | name, (FInt32|FUInt32) ->
9114 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9117 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9119 | name, FOptPercent ->
9120 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9123 pr " free (%s);\n" n
9125 (* Generate Sys/Guestfs.pm. *)
9126 and generate_perl_pm () =
9127 generate_header HashStyle LGPLv2plus;
9134 Sys::Guestfs - Perl bindings for libguestfs
9140 my $h = Sys::Guestfs->new ();
9141 $h->add_drive ('guest.img');
9143 $h->mount ('/dev/sda1', '/');
9144 $h->touch ('/hello');
9149 The C<Sys::Guestfs> module provides a Perl XS binding to the
9150 libguestfs API for examining and modifying virtual machine
9153 Amongst the things this is good for: making batch configuration
9154 changes to guests, getting disk used/free statistics (see also:
9155 virt-df), migrating between virtualization systems (see also:
9156 virt-p2v), performing partial backups, performing partial guest
9157 clones, cloning guests and changing registry/UUID/hostname info, and
9160 Libguestfs uses Linux kernel and qemu code, and can access any type of
9161 guest filesystem that Linux and qemu can, including but not limited
9162 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9163 schemes, qcow, qcow2, vmdk.
9165 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9166 LVs, what filesystem is in each LV, etc.). It can also run commands
9167 in the context of the guest. Also you can access filesystems over
9170 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9171 functions for using libguestfs from Perl, including integration
9176 All errors turn into calls to C<croak> (see L<Carp(3)>).
9184 package Sys::Guestfs;
9189 # This version number changes whenever a new function
9190 # is added to the libguestfs API. It is not directly
9191 # related to the libguestfs version number.
9192 use vars qw($VERSION);
9196 XSLoader::load ('Sys::Guestfs');
9198 =item $h = Sys::Guestfs->new ();
9200 Create a new guestfs handle.
9206 my $class = ref ($proto) || $proto;
9208 my $g = Sys::Guestfs::_create ();
9209 my $self = { _g => $g };
9210 bless $self, $class;
9216 Explicitly close the guestfs handle.
9218 B<Note:> You should not usually call this function. The handle will
9219 be closed implicitly when its reference count goes to zero (eg.
9220 when it goes out of scope or the program ends). This call is
9221 only required in some exceptional cases, such as where the program
9222 may contain cached references to the handle 'somewhere' and you
9223 really have to have the close happen right away. After calling
9224 C<close> the program must not call any method (including C<close>)
9225 on the handle (but the implicit call to C<DESTROY> that happens
9226 when the final reference is cleaned up is OK).
9232 (* Actions. We only need to print documentation for these as
9233 * they are pulled in from the XS code automatically.
9236 fun (name, style, _, flags, _, _, longdesc) ->
9237 if not (List.mem NotInDocs flags) then (
9238 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9240 generate_perl_prototype name style;
9242 pr "%s\n\n" longdesc;
9243 if List.mem ProtocolLimitWarning flags then
9244 pr "%s\n\n" protocol_limit_warning;
9245 if List.mem DangerWillRobinson flags then
9246 pr "%s\n\n" danger_will_robinson;
9247 match deprecation_notice flags with
9249 | Some txt -> pr "%s\n\n" txt
9251 ) all_functions_sorted;
9263 Copyright (C) %s Red Hat Inc.
9267 Please see the file COPYING.LIB for the full license.
9273 L<http://libguestfs.org>,
9274 L<Sys::Guestfs::Lib(3)>.
9279 and generate_perl_prototype name style =
9280 (match fst style with
9288 | RBufferOut n -> pr "$%s = " n
9290 | RHashtable n -> pr "%%%s = " n
9292 | RStructList (n,_) -> pr "@%s = " n
9295 let comma = ref false in
9298 if !comma then pr ", ";
9301 | Pathname n | Device n | Dev_or_Path n | String n
9302 | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9305 | StringList n | DeviceList n ->
9310 (* Generate Python C module. *)
9311 and generate_python_c () =
9312 generate_header CStyle LGPLv2plus;
9315 #define PY_SSIZE_T_CLEAN 1
9318 #if PY_VERSION_HEX < 0x02050000
9319 typedef int Py_ssize_t;
9320 #define PY_SSIZE_T_MAX INT_MAX
9321 #define PY_SSIZE_T_MIN INT_MIN
9328 #include \"guestfs.h\"
9336 get_handle (PyObject *obj)
9339 assert (obj != Py_None);
9340 return ((Pyguestfs_Object *) obj)->g;
9344 put_handle (guestfs_h *g)
9348 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9351 /* This list should be freed (but not the strings) after use. */
9353 get_string_list (PyObject *obj)
9360 if (!PyList_Check (obj)) {
9361 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9365 Py_ssize_t slen = PyList_Size (obj);
9367 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9370 len = (size_t) slen;
9371 r = malloc (sizeof (char *) * (len+1));
9373 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9377 for (i = 0; i < len; ++i)
9378 r[i] = PyString_AsString (PyList_GetItem (obj, i));
9385 put_string_list (char * const * const argv)
9390 for (argc = 0; argv[argc] != NULL; ++argc)
9393 list = PyList_New (argc);
9394 for (i = 0; i < argc; ++i)
9395 PyList_SetItem (list, i, PyString_FromString (argv[i]));
9401 put_table (char * const * const argv)
9403 PyObject *list, *item;
9406 for (argc = 0; argv[argc] != NULL; ++argc)
9409 list = PyList_New (argc >> 1);
9410 for (i = 0; i < argc; i += 2) {
9411 item = PyTuple_New (2);
9412 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9413 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9414 PyList_SetItem (list, i >> 1, item);
9421 free_strings (char **argv)
9425 for (argc = 0; argv[argc] != NULL; ++argc)
9431 py_guestfs_create (PyObject *self, PyObject *args)
9435 g = guestfs_create ();
9437 PyErr_SetString (PyExc_RuntimeError,
9438 \"guestfs.create: failed to allocate handle\");
9441 guestfs_set_error_handler (g, NULL, NULL);
9442 return put_handle (g);
9446 py_guestfs_close (PyObject *self, PyObject *args)
9451 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9453 g = get_handle (py_g);
9457 Py_INCREF (Py_None);
9463 let emit_put_list_function typ =
9464 pr "static PyObject *\n";
9465 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9467 pr " PyObject *list;\n";
9470 pr " list = PyList_New (%ss->len);\n" typ;
9471 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
9472 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9473 pr " return list;\n";
9478 (* Structures, turned into Python dictionaries. *)
9481 pr "static PyObject *\n";
9482 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9484 pr " PyObject *dict;\n";
9486 pr " dict = PyDict_New ();\n";
9490 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9491 pr " PyString_FromString (%s->%s));\n"
9494 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9495 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9498 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9499 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
9501 | name, (FBytes|FUInt64) ->
9502 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9503 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
9506 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9507 pr " PyLong_FromLongLong (%s->%s));\n"
9510 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9511 pr " PyLong_FromUnsignedLong (%s->%s));\n"
9514 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9515 pr " PyLong_FromLong (%s->%s));\n"
9517 | name, FOptPercent ->
9518 pr " if (%s->%s >= 0)\n" typ name;
9519 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9520 pr " PyFloat_FromDouble ((double) %s->%s));\n"
9523 pr " Py_INCREF (Py_None);\n";
9524 pr " PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9527 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
9528 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9530 pr " return dict;\n";
9536 (* Emit a put_TYPE_list function definition only if that function is used. *)
9539 | typ, (RStructListOnly | RStructAndList) ->
9540 (* generate the function for typ *)
9541 emit_put_list_function typ
9542 | typ, _ -> () (* empty *)
9543 ) (rstructs_used_by all_functions);
9545 (* Python wrapper functions. *)
9547 fun (name, style, _, _, _, _, _) ->
9548 pr "static PyObject *\n";
9549 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9552 pr " PyObject *py_g;\n";
9553 pr " guestfs_h *g;\n";
9554 pr " PyObject *py_r;\n";
9557 match fst style with
9558 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9559 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9560 | RConstString _ | RConstOptString _ ->
9561 pr " const char *r;\n"; "NULL"
9562 | RString _ -> pr " char *r;\n"; "NULL"
9563 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9564 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9565 | RStructList (_, typ) ->
9566 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9569 pr " size_t size;\n";
9574 | Pathname n | Device n | Dev_or_Path n | String n
9575 | FileIn n | FileOut n ->
9576 pr " const char *%s;\n" n
9577 | OptString n -> pr " const char *%s;\n" n
9579 pr " const char *%s;\n" n;
9580 pr " Py_ssize_t %s_size;\n" n
9581 | StringList n | DeviceList n ->
9582 pr " PyObject *py_%s;\n" n;
9583 pr " char **%s;\n" n
9584 | Bool n -> pr " int %s;\n" n
9585 | Int n -> pr " int %s;\n" n
9586 | Int64 n -> pr " long long %s;\n" n
9591 (* Convert the parameters. *)
9592 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
9595 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9596 | OptString _ -> pr "z"
9597 | StringList _ | DeviceList _ -> pr "O"
9598 | Bool _ -> pr "i" (* XXX Python has booleans? *)
9600 | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9601 * emulate C's int/long/long long in Python?
9603 | BufferIn _ -> pr "s#"
9605 pr ":guestfs_%s\",\n" name;
9609 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9610 | OptString n -> pr ", &%s" n
9611 | StringList n | DeviceList n -> pr ", &py_%s" n
9612 | Bool n -> pr ", &%s" n
9613 | Int n -> pr ", &%s" n
9614 | Int64 n -> pr ", &%s" n
9615 | BufferIn n -> pr ", &%s, &%s_size" n n
9619 pr " return NULL;\n";
9621 pr " g = get_handle (py_g);\n";
9624 | Pathname _ | Device _ | Dev_or_Path _ | String _
9625 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9627 | StringList n | DeviceList n ->
9628 pr " %s = get_string_list (py_%s);\n" n n;
9629 pr " if (!%s) return NULL;\n" n
9634 pr " r = guestfs_%s " name;
9635 generate_c_call_args ~handle:"g" style;
9640 | Pathname _ | Device _ | Dev_or_Path _ | String _
9641 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9643 | StringList n | DeviceList n ->
9644 pr " free (%s);\n" n
9647 pr " if (r == %s) {\n" error_code;
9648 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9649 pr " return NULL;\n";
9653 (match fst style with
9655 pr " Py_INCREF (Py_None);\n";
9656 pr " py_r = Py_None;\n"
9658 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
9659 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
9660 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
9661 | RConstOptString _ ->
9663 pr " py_r = PyString_FromString (r);\n";
9665 pr " Py_INCREF (Py_None);\n";
9666 pr " py_r = Py_None;\n";
9669 pr " py_r = PyString_FromString (r);\n";
9672 pr " py_r = put_string_list (r);\n";
9673 pr " free_strings (r);\n"
9674 | RStruct (_, typ) ->
9675 pr " py_r = put_%s (r);\n" typ;
9676 pr " guestfs_free_%s (r);\n" typ
9677 | RStructList (_, typ) ->
9678 pr " py_r = put_%s_list (r);\n" typ;
9679 pr " guestfs_free_%s_list (r);\n" typ
9681 pr " py_r = put_table (r);\n";
9682 pr " free_strings (r);\n"
9684 pr " py_r = PyString_FromStringAndSize (r, size);\n";
9688 pr " return py_r;\n";
9693 (* Table of functions. *)
9694 pr "static PyMethodDef methods[] = {\n";
9695 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9696 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9698 fun (name, _, _, _, _, _, _) ->
9699 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9702 pr " { NULL, NULL, 0, NULL }\n";
9706 (* Init function. *)
9709 initlibguestfsmod (void)
9711 static int initialized = 0;
9713 if (initialized) return;
9714 Py_InitModule ((char *) \"libguestfsmod\", methods);
9719 (* Generate Python module. *)
9720 and generate_python_py () =
9721 generate_header HashStyle LGPLv2plus;
9724 u\"\"\"Python bindings for libguestfs
9727 g = guestfs.GuestFS ()
9728 g.add_drive (\"guest.img\")
9730 parts = g.list_partitions ()
9732 The guestfs module provides a Python binding to the libguestfs API
9733 for examining and modifying virtual machine disk images.
9735 Amongst the things this is good for: making batch configuration
9736 changes to guests, getting disk used/free statistics (see also:
9737 virt-df), migrating between virtualization systems (see also:
9738 virt-p2v), performing partial backups, performing partial guest
9739 clones, cloning guests and changing registry/UUID/hostname info, and
9742 Libguestfs uses Linux kernel and qemu code, and can access any type of
9743 guest filesystem that Linux and qemu can, including but not limited
9744 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9745 schemes, qcow, qcow2, vmdk.
9747 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9748 LVs, what filesystem is in each LV, etc.). It can also run commands
9749 in the context of the guest. Also you can access filesystems over
9752 Errors which happen while using the API are turned into Python
9753 RuntimeError exceptions.
9755 To create a guestfs handle you usually have to perform the following
9758 # Create the handle, call add_drive at least once, and possibly
9759 # several times if the guest has multiple block devices:
9760 g = guestfs.GuestFS ()
9761 g.add_drive (\"guest.img\")
9763 # Launch the qemu subprocess and wait for it to become ready:
9766 # Now you can issue commands, for example:
9771 import libguestfsmod
9774 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9776 def __init__ (self):
9777 \"\"\"Create a new libguestfs handle.\"\"\"
9778 self._o = libguestfsmod.create ()
9781 libguestfsmod.close (self._o)
9786 fun (name, style, _, flags, _, _, longdesc) ->
9788 generate_py_call_args ~handle:"self" (snd style);
9791 if not (List.mem NotInDocs flags) then (
9792 let doc = replace_str longdesc "C<guestfs_" "C<g." in
9794 match fst style with
9795 | RErr | RInt _ | RInt64 _ | RBool _
9796 | RConstOptString _ | RConstString _
9797 | RString _ | RBufferOut _ -> doc
9799 doc ^ "\n\nThis function returns a list of strings."
9800 | RStruct (_, typ) ->
9801 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9802 | RStructList (_, typ) ->
9803 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
9805 doc ^ "\n\nThis function returns a dictionary." in
9807 if List.mem ProtocolLimitWarning flags then
9808 doc ^ "\n\n" ^ protocol_limit_warning
9811 if List.mem DangerWillRobinson flags then
9812 doc ^ "\n\n" ^ danger_will_robinson
9815 match deprecation_notice flags with
9817 | Some txt -> doc ^ "\n\n" ^ txt in
9818 let doc = pod2text ~width:60 name doc in
9819 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9820 let doc = String.concat "\n " doc in
9821 pr " u\"\"\"%s\"\"\"\n" doc;
9823 pr " return libguestfsmod.%s " name;
9824 generate_py_call_args ~handle:"self._o" (snd style);
9829 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9830 and generate_py_call_args ~handle args =
9832 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9835 (* Useful if you need the longdesc POD text as plain text. Returns a
9838 * Because this is very slow (the slowest part of autogeneration),
9839 * we memoize the results.
9841 and pod2text ~width name longdesc =
9842 let key = width, name, longdesc in
9843 try Hashtbl.find pod2text_memo key
9845 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9846 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9848 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9849 let chan = open_process_in cmd in
9850 let lines = ref [] in
9852 let line = input_line chan in
9853 if i = 1 then (* discard the first line of output *)
9856 let line = triml line in
9857 lines := line :: !lines;
9860 let lines = try loop 1 with End_of_file -> List.rev !lines in
9862 (match close_process_in chan with
9865 failwithf "pod2text: process exited with non-zero status (%d)" i
9866 | WSIGNALED i | WSTOPPED i ->
9867 failwithf "pod2text: process signalled or stopped by signal %d" i
9869 Hashtbl.add pod2text_memo key lines;
9870 pod2text_memo_updated ();
9873 (* Generate ruby bindings. *)
9874 and generate_ruby_c () =
9875 generate_header CStyle LGPLv2plus;
9883 #include \"guestfs.h\"
9885 #include \"extconf.h\"
9887 /* For Ruby < 1.9 */
9889 #define RARRAY_LEN(r) (RARRAY((r))->len)
9892 static VALUE m_guestfs; /* guestfs module */
9893 static VALUE c_guestfs; /* guestfs_h handle */
9894 static VALUE e_Error; /* used for all errors */
9896 static void ruby_guestfs_free (void *p)
9899 guestfs_close ((guestfs_h *) p);
9902 static VALUE ruby_guestfs_create (VALUE m)
9906 g = guestfs_create ();
9908 rb_raise (e_Error, \"failed to create guestfs handle\");
9910 /* Don't print error messages to stderr by default. */
9911 guestfs_set_error_handler (g, NULL, NULL);
9913 /* Wrap it, and make sure the close function is called when the
9916 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9919 static VALUE ruby_guestfs_close (VALUE gv)
9922 Data_Get_Struct (gv, guestfs_h, g);
9924 ruby_guestfs_free (g);
9925 DATA_PTR (gv) = NULL;
9933 fun (name, style, _, _, _, _, _) ->
9934 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9935 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9938 pr " guestfs_h *g;\n";
9939 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
9941 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9947 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9948 pr " Check_Type (%sv, T_STRING);\n" n;
9949 pr " const char *%s = StringValueCStr (%sv);\n" n n;
9951 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9952 pr " \"%s\", \"%s\");\n" n name
9954 pr " Check_Type (%sv, T_STRING);\n" n;
9955 pr " const char *%s = RSTRING (%sv)->ptr;\n" n n;
9957 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9958 pr " \"%s\", \"%s\");\n" n name;
9959 pr " size_t %s_size = RSTRING (%sv)->len;\n" n n
9961 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9962 | StringList n | DeviceList n ->
9963 pr " char **%s;\n" n;
9964 pr " Check_Type (%sv, T_ARRAY);\n" n;
9966 pr " size_t i, len;\n";
9967 pr " len = RARRAY_LEN (%sv);\n" n;
9968 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9970 pr " for (i = 0; i < len; ++i) {\n";
9971 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
9972 pr " %s[i] = StringValueCStr (v);\n" n;
9974 pr " %s[len] = NULL;\n" n;
9977 pr " int %s = RTEST (%sv);\n" n n
9979 pr " int %s = NUM2INT (%sv);\n" n n
9981 pr " long long %s = NUM2LL (%sv);\n" n n
9986 match fst style with
9987 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
9988 | RInt64 _ -> pr " int64_t r;\n"; "-1"
9989 | RConstString _ | RConstOptString _ ->
9990 pr " const char *r;\n"; "NULL"
9991 | RString _ -> pr " char *r;\n"; "NULL"
9992 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
9993 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
9994 | RStructList (_, typ) ->
9995 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
9998 pr " size_t size;\n";
10002 pr " r = guestfs_%s " name;
10003 generate_c_call_args ~handle:"g" style;
10008 | Pathname _ | Device _ | Dev_or_Path _ | String _
10009 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10011 | StringList n | DeviceList n ->
10012 pr " free (%s);\n" n
10015 pr " if (r == %s)\n" error_code;
10016 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10019 (match fst style with
10021 pr " return Qnil;\n"
10022 | RInt _ | RBool _ ->
10023 pr " return INT2NUM (r);\n"
10025 pr " return ULL2NUM (r);\n"
10026 | RConstString _ ->
10027 pr " return rb_str_new2 (r);\n";
10028 | RConstOptString _ ->
10030 pr " return rb_str_new2 (r);\n";
10032 pr " return Qnil;\n";
10034 pr " VALUE rv = rb_str_new2 (r);\n";
10036 pr " return rv;\n";
10038 pr " size_t i, len = 0;\n";
10039 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
10040 pr " VALUE rv = rb_ary_new2 (len);\n";
10041 pr " for (i = 0; r[i] != NULL; ++i) {\n";
10042 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10043 pr " free (r[i]);\n";
10047 | RStruct (_, typ) ->
10048 let cols = cols_of_struct typ in
10049 generate_ruby_struct_code typ cols
10050 | RStructList (_, typ) ->
10051 let cols = cols_of_struct typ in
10052 generate_ruby_struct_list_code typ cols
10054 pr " VALUE rv = rb_hash_new ();\n";
10056 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
10057 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10058 pr " free (r[i]);\n";
10059 pr " free (r[i+1]);\n";
10064 pr " VALUE rv = rb_str_new (r, size);\n";
10066 pr " return rv;\n";
10074 /* Initialize the module. */
10075 void Init__guestfs ()
10077 m_guestfs = rb_define_module (\"Guestfs\");
10078 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10079 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10081 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10082 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10085 (* Define the rest of the methods. *)
10087 fun (name, style, _, _, _, _, _) ->
10088 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
10089 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10094 (* Ruby code to return a struct. *)
10095 and generate_ruby_struct_code typ cols =
10096 pr " VALUE rv = rb_hash_new ();\n";
10100 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10102 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10104 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10105 | name, (FBytes|FUInt64) ->
10106 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10108 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10110 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10112 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10113 | name, FOptPercent ->
10114 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10115 | name, FChar -> (* XXX wrong? *)
10116 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10118 pr " guestfs_free_%s (r);\n" typ;
10121 (* Ruby code to return a struct list. *)
10122 and generate_ruby_struct_list_code typ cols =
10123 pr " VALUE rv = rb_ary_new2 (r->len);\n";
10125 pr " for (i = 0; i < r->len; ++i) {\n";
10126 pr " VALUE hv = rb_hash_new ();\n";
10130 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10132 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
10134 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10135 | name, (FBytes|FUInt64) ->
10136 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10138 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10140 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10142 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10143 | name, FOptPercent ->
10144 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10145 | name, FChar -> (* XXX wrong? *)
10146 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10148 pr " rb_ary_push (rv, hv);\n";
10150 pr " guestfs_free_%s_list (r);\n" typ;
10153 (* Generate Java bindings GuestFS.java file. *)
10154 and generate_java_java () =
10155 generate_header CStyle LGPLv2plus;
10158 package com.redhat.et.libguestfs;
10160 import java.util.HashMap;
10161 import com.redhat.et.libguestfs.LibGuestFSException;
10162 import com.redhat.et.libguestfs.PV;
10163 import com.redhat.et.libguestfs.VG;
10164 import com.redhat.et.libguestfs.LV;
10165 import com.redhat.et.libguestfs.Stat;
10166 import com.redhat.et.libguestfs.StatVFS;
10167 import com.redhat.et.libguestfs.IntBool;
10168 import com.redhat.et.libguestfs.Dirent;
10171 * The GuestFS object is a libguestfs handle.
10175 public class GuestFS {
10176 // Load the native code.
10178 System.loadLibrary (\"guestfs_jni\");
10182 * The native guestfs_h pointer.
10187 * Create a libguestfs handle.
10189 * @throws LibGuestFSException
10191 public GuestFS () throws LibGuestFSException
10195 private native long _create () throws LibGuestFSException;
10198 * Close a libguestfs handle.
10200 * You can also leave handles to be collected by the garbage
10201 * collector, but this method ensures that the resources used
10202 * by the handle are freed up immediately. If you call any
10203 * other methods after closing the handle, you will get an
10206 * @throws LibGuestFSException
10208 public void close () throws LibGuestFSException
10214 private native void _close (long g) throws LibGuestFSException;
10216 public void finalize () throws LibGuestFSException
10224 fun (name, style, _, flags, _, shortdesc, longdesc) ->
10225 if not (List.mem NotInDocs flags); then (
10226 let doc = replace_str longdesc "C<guestfs_" "C<g." in
10228 if List.mem ProtocolLimitWarning flags then
10229 doc ^ "\n\n" ^ protocol_limit_warning
10232 if List.mem DangerWillRobinson flags then
10233 doc ^ "\n\n" ^ danger_will_robinson
10236 match deprecation_notice flags with
10238 | Some txt -> doc ^ "\n\n" ^ txt in
10239 let doc = pod2text ~width:60 name doc in
10240 let doc = List.map ( (* RHBZ#501883 *)
10243 | nonempty -> nonempty
10245 let doc = String.concat "\n * " doc in
10248 pr " * %s\n" shortdesc;
10251 pr " * @throws LibGuestFSException\n";
10255 generate_java_prototype ~public:true ~semicolon:false name style;
10258 pr " if (g == 0)\n";
10259 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
10262 if fst style <> RErr then pr "return ";
10264 generate_java_call_args ~handle:"g" (snd style);
10268 generate_java_prototype ~privat:true ~native:true name style;
10275 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10276 and generate_java_call_args ~handle args =
10278 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10281 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10282 ?(semicolon=true) name style =
10283 if privat then pr "private ";
10284 if public then pr "public ";
10285 if native then pr "native ";
10288 (match fst style with
10289 | RErr -> pr "void ";
10290 | RInt _ -> pr "int ";
10291 | RInt64 _ -> pr "long ";
10292 | RBool _ -> pr "boolean ";
10293 | RConstString _ | RConstOptString _ | RString _
10294 | RBufferOut _ -> pr "String ";
10295 | RStringList _ -> pr "String[] ";
10296 | RStruct (_, typ) ->
10297 let name = java_name_of_struct typ in
10299 | RStructList (_, typ) ->
10300 let name = java_name_of_struct typ in
10302 | RHashtable _ -> pr "HashMap<String,String> ";
10305 if native then pr "_%s " name else pr "%s " name;
10307 let needs_comma = ref false in
10310 needs_comma := true
10316 if !needs_comma then pr ", ";
10317 needs_comma := true;
10321 | Device n | Dev_or_Path n
10329 | StringList n | DeviceList n ->
10340 pr " throws LibGuestFSException";
10341 if semicolon then pr ";"
10343 and generate_java_struct jtyp cols () =
10344 generate_header CStyle LGPLv2plus;
10347 package com.redhat.et.libguestfs;
10350 * Libguestfs %s structure.
10362 | name, FBuffer -> pr " public String %s;\n" name
10363 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
10364 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
10365 | name, FChar -> pr " public char %s;\n" name
10366 | name, FOptPercent ->
10367 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
10368 pr " public float %s;\n" name
10373 and generate_java_c () =
10374 generate_header CStyle LGPLv2plus;
10378 #include <stdlib.h>
10379 #include <string.h>
10381 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10382 #include \"guestfs.h\"
10384 /* Note that this function returns. The exception is not thrown
10385 * until after the wrapper function returns.
10388 throw_exception (JNIEnv *env, const char *msg)
10391 cl = (*env)->FindClass (env,
10392 \"com/redhat/et/libguestfs/LibGuestFSException\");
10393 (*env)->ThrowNew (env, cl, msg);
10396 JNIEXPORT jlong JNICALL
10397 Java_com_redhat_et_libguestfs_GuestFS__1create
10398 (JNIEnv *env, jobject obj)
10402 g = guestfs_create ();
10404 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10407 guestfs_set_error_handler (g, NULL, NULL);
10408 return (jlong) (long) g;
10411 JNIEXPORT void JNICALL
10412 Java_com_redhat_et_libguestfs_GuestFS__1close
10413 (JNIEnv *env, jobject obj, jlong jg)
10415 guestfs_h *g = (guestfs_h *) (long) jg;
10422 fun (name, style, _, _, _, _, _) ->
10424 (match fst style with
10425 | RErr -> pr "void ";
10426 | RInt _ -> pr "jint ";
10427 | RInt64 _ -> pr "jlong ";
10428 | RBool _ -> pr "jboolean ";
10429 | RConstString _ | RConstOptString _ | RString _
10430 | RBufferOut _ -> pr "jstring ";
10431 | RStruct _ | RHashtable _ ->
10433 | RStringList _ | RStructList _ ->
10434 pr "jobjectArray ";
10437 pr "Java_com_redhat_et_libguestfs_GuestFS_";
10438 pr "%s" (replace_str ("_" ^ name) "_" "_1");
10440 pr " (JNIEnv *env, jobject obj, jlong jg";
10444 | Device n | Dev_or_Path n
10449 pr ", jstring j%s" n
10451 pr ", jbyteArray j%s" n
10452 | StringList n | DeviceList n ->
10453 pr ", jobjectArray j%s" n
10455 pr ", jboolean j%s" n
10463 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
10464 let error_code, no_ret =
10465 match fst style with
10466 | RErr -> pr " int r;\n"; "-1", ""
10468 | RInt _ -> pr " int r;\n"; "-1", "0"
10469 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
10470 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
10471 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
10473 pr " jstring jr;\n";
10474 pr " char *r;\n"; "NULL", "NULL"
10476 pr " jobjectArray jr;\n";
10477 pr " int r_len;\n";
10478 pr " jclass cl;\n";
10479 pr " jstring jstr;\n";
10480 pr " char **r;\n"; "NULL", "NULL"
10481 | RStruct (_, typ) ->
10482 pr " jobject jr;\n";
10483 pr " jclass cl;\n";
10484 pr " jfieldID fl;\n";
10485 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10486 | RStructList (_, typ) ->
10487 pr " jobjectArray jr;\n";
10488 pr " jclass cl;\n";
10489 pr " jfieldID fl;\n";
10490 pr " jobject jfl;\n";
10491 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10492 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
10494 pr " jstring jr;\n";
10496 pr " size_t size;\n";
10501 | Device n | Dev_or_Path n
10506 pr " const char *%s;\n" n
10508 pr " jbyte *%s;\n" n;
10509 pr " size_t %s_size;\n" n
10510 | StringList n | DeviceList n ->
10511 pr " int %s_len;\n" n;
10512 pr " const char **%s;\n" n
10517 pr " int64_t %s;\n" n
10521 (match fst style with
10522 | RStringList _ | RStructList _ -> true
10523 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10524 | RConstOptString _
10525 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10526 List.exists (function
10527 | StringList _ -> true
10528 | DeviceList _ -> true
10529 | _ -> false) (snd style) in
10535 (* Get the parameters. *)
10539 | Device n | Dev_or_Path n
10543 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10545 (* This is completely undocumented, but Java null becomes
10546 * a NULL parameter.
10548 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10550 pr " %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10551 pr " %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10552 | StringList n | DeviceList n ->
10553 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10554 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10555 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10556 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10558 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10560 pr " %s[%s_len] = NULL;\n" n n;
10564 pr " %s = j%s;\n" n n
10567 (* Make the call. *)
10568 pr " r = guestfs_%s " name;
10569 generate_c_call_args ~handle:"g" style;
10572 (* Release the parameters. *)
10576 | Device n | Dev_or_Path n
10580 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10582 pr " if (j%s)\n" n;
10583 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10585 pr " (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10586 | StringList n | DeviceList n ->
10587 pr " for (i = 0; i < %s_len; ++i) {\n" n;
10588 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10590 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10592 pr " free (%s);\n" n
10598 (* Check for errors. *)
10599 pr " if (r == %s) {\n" error_code;
10600 pr " throw_exception (env, guestfs_last_error (g));\n";
10601 pr " return %s;\n" no_ret;
10604 (* Return value. *)
10605 (match fst style with
10607 | RInt _ -> pr " return (jint) r;\n"
10608 | RBool _ -> pr " return (jboolean) r;\n"
10609 | RInt64 _ -> pr " return (jlong) r;\n"
10610 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
10611 | RConstOptString _ ->
10612 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10614 pr " jr = (*env)->NewStringUTF (env, r);\n";
10618 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10619 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10620 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
10621 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10622 pr " for (i = 0; i < r_len; ++i) {\n";
10623 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
10624 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10625 pr " free (r[i]);\n";
10629 | RStruct (_, typ) ->
10630 let jtyp = java_name_of_struct typ in
10631 let cols = cols_of_struct typ in
10632 generate_java_struct_return typ jtyp cols
10633 | RStructList (_, typ) ->
10634 let jtyp = java_name_of_struct typ in
10635 let cols = cols_of_struct typ in
10636 generate_java_struct_list_return typ jtyp cols
10639 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10640 pr " return NULL;\n"
10642 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10651 and generate_java_struct_return typ jtyp cols =
10652 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10653 pr " jr = (*env)->AllocObject (env, cl);\n";
10657 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10658 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10661 pr " char s[33];\n";
10662 pr " memcpy (s, r->%s, 32);\n" name;
10663 pr " s[32] = 0;\n";
10664 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10665 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10669 pr " int len = r->%s_len;\n" name;
10670 pr " char s[len+1];\n";
10671 pr " memcpy (s, r->%s, len);\n" name;
10672 pr " s[len] = 0;\n";
10673 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10674 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10676 | name, (FBytes|FUInt64|FInt64) ->
10677 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10678 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10679 | name, (FUInt32|FInt32) ->
10680 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10681 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10682 | name, FOptPercent ->
10683 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10684 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10686 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10687 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10692 and generate_java_struct_list_return typ jtyp cols =
10693 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10694 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10695 pr " for (i = 0; i < r->len; ++i) {\n";
10696 pr " jfl = (*env)->AllocObject (env, cl);\n";
10700 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10701 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10704 pr " char s[33];\n";
10705 pr " memcpy (s, r->val[i].%s, 32);\n" name;
10706 pr " s[32] = 0;\n";
10707 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10708 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10712 pr " int len = r->val[i].%s_len;\n" name;
10713 pr " char s[len+1];\n";
10714 pr " memcpy (s, r->val[i].%s, len);\n" name;
10715 pr " s[len] = 0;\n";
10716 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10717 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10719 | name, (FBytes|FUInt64|FInt64) ->
10720 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10721 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10722 | name, (FUInt32|FInt32) ->
10723 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10724 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10725 | name, FOptPercent ->
10726 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10727 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10729 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10730 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10732 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10734 pr " guestfs_free_%s_list (r);\n" typ;
10737 and generate_java_makefile_inc () =
10738 generate_header HashStyle GPLv2plus;
10740 pr "java_built_sources = \\\n";
10743 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10745 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10747 and generate_haskell_hs () =
10748 generate_header HaskellStyle LGPLv2plus;
10750 (* XXX We only know how to generate partial FFI for Haskell
10751 * at the moment. Please help out!
10753 let can_generate style =
10757 | RInt64 _, _ -> true
10759 | RConstString _, _
10760 | RConstOptString _, _
10766 | RBufferOut _, _ -> false in
10769 {-# INCLUDE <guestfs.h> #-}
10770 {-# LANGUAGE ForeignFunctionInterface #-}
10775 (* List out the names of the actions we want to export. *)
10777 fun (name, style, _, _, _, _, _) ->
10778 if can_generate style then pr ",\n %s" name
10784 -- Unfortunately some symbols duplicate ones already present
10785 -- in Prelude. We don't know which, so we hard-code a list
10787 import Prelude hiding (truncate)
10791 import Foreign.C.Types
10793 import Control.Exception
10794 import Data.Typeable
10796 data GuestfsS = GuestfsS -- represents the opaque C struct
10797 type GuestfsP = Ptr GuestfsS -- guestfs_h *
10798 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10800 -- XXX define properly later XXX
10804 data IntBool = IntBool
10806 data StatVFS = StatVFS
10807 data Hashtable = Hashtable
10809 foreign import ccall unsafe \"guestfs_create\" c_create
10811 foreign import ccall unsafe \"&guestfs_close\" c_close
10812 :: FunPtr (GuestfsP -> IO ())
10813 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10814 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10816 create :: IO GuestfsH
10819 c_set_error_handler p nullPtr nullPtr
10820 h <- newForeignPtr c_close p
10823 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10824 :: GuestfsP -> IO CString
10826 -- last_error :: GuestfsH -> IO (Maybe String)
10827 -- last_error h = do
10828 -- str <- withForeignPtr h (\\p -> c_last_error p)
10829 -- maybePeek peekCString str
10831 last_error :: GuestfsH -> IO (String)
10833 str <- withForeignPtr h (\\p -> c_last_error p)
10834 if (str == nullPtr)
10835 then return \"no error\"
10836 else peekCString str
10840 (* Generate wrappers for each foreign function. *)
10842 fun (name, style, _, _, _, _, _) ->
10843 if can_generate style then (
10844 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10846 generate_haskell_prototype ~handle:"GuestfsP" style;
10850 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10852 pr "%s %s = do\n" name
10853 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10855 (* Convert pointer arguments using with* functions. *)
10860 | Pathname n | Device n | Dev_or_Path n | String n ->
10861 pr "withCString %s $ \\%s -> " n n
10863 pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10864 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10865 | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10866 | Bool _ | Int _ | Int64 _ -> ()
10868 (* Convert integer arguments. *)
10872 | Bool n -> sprintf "(fromBool %s)" n
10873 | Int n -> sprintf "(fromIntegral %s)" n
10874 | Int64 n -> sprintf "(fromIntegral %s)" n
10875 | FileIn n | FileOut n
10876 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10877 | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10879 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10880 (String.concat " " ("p" :: args));
10881 (match fst style with
10882 | RErr | RInt _ | RInt64 _ | RBool _ ->
10883 pr " if (r == -1)\n";
10885 pr " err <- last_error h\n";
10887 | RConstString _ | RConstOptString _ | RString _
10888 | RStringList _ | RStruct _
10889 | RStructList _ | RHashtable _ | RBufferOut _ ->
10890 pr " if (r == nullPtr)\n";
10892 pr " err <- last_error h\n";
10895 (match fst style with
10897 pr " else return ()\n"
10899 pr " else return (fromIntegral r)\n"
10901 pr " else return (fromIntegral r)\n"
10903 pr " else return (toBool r)\n"
10905 | RConstOptString _
10912 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10918 and generate_haskell_prototype ~handle ?(hs = false) style =
10919 pr "%s -> " handle;
10920 let string = if hs then "String" else "CString" in
10921 let int = if hs then "Int" else "CInt" in
10922 let bool = if hs then "Bool" else "CInt" in
10923 let int64 = if hs then "Integer" else "Int64" in
10927 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10929 if hs then pr "String"
10930 else pr "CString -> CInt"
10931 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10932 | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10933 | Bool _ -> pr "%s" bool
10934 | Int _ -> pr "%s" int
10935 | Int64 _ -> pr "%s" int
10936 | FileIn _ -> pr "%s" string
10937 | FileOut _ -> pr "%s" string
10942 (match fst style with
10943 | RErr -> if not hs then pr "CInt"
10944 | RInt _ -> pr "%s" int
10945 | RInt64 _ -> pr "%s" int64
10946 | RBool _ -> pr "%s" bool
10947 | RConstString _ -> pr "%s" string
10948 | RConstOptString _ -> pr "Maybe %s" string
10949 | RString _ -> pr "%s" string
10950 | RStringList _ -> pr "[%s]" string
10951 | RStruct (_, typ) ->
10952 let name = java_name_of_struct typ in
10954 | RStructList (_, typ) ->
10955 let name = java_name_of_struct typ in
10957 | RHashtable _ -> pr "Hashtable"
10958 | RBufferOut _ -> pr "%s" string
10962 and generate_csharp () =
10963 generate_header CPlusPlusStyle LGPLv2plus;
10965 (* XXX Make this configurable by the C# assembly users. *)
10966 let library = "libguestfs.so.0" in
10969 // These C# bindings are highly experimental at present.
10971 // Firstly they only work on Linux (ie. Mono). In order to get them
10972 // to work on Windows (ie. .Net) you would need to port the library
10973 // itself to Windows first.
10975 // The second issue is that some calls are known to be incorrect and
10976 // can cause Mono to segfault. Particularly: calls which pass or
10977 // return string[], or return any structure value. This is because
10978 // we haven't worked out the correct way to do this from C#.
10980 // The third issue is that when compiling you get a lot of warnings.
10981 // We are not sure whether the warnings are important or not.
10983 // Fourthly we do not routinely build or test these bindings as part
10984 // of the make && make check cycle, which means that regressions might
10987 // Suggestions and patches are welcome.
10991 // gmcs Libguestfs.cs
10992 // mono Libguestfs.exe
10994 // (You'll probably want to add a Test class / static main function
10995 // otherwise this won't do anything useful).
10999 using System.Runtime.InteropServices;
11000 using System.Runtime.Serialization;
11001 using System.Collections;
11005 class Error : System.ApplicationException
11007 public Error (string message) : base (message) {}
11008 protected Error (SerializationInfo info, StreamingContext context) {}
11015 [DllImport (\"%s\")]
11016 static extern IntPtr guestfs_create ();
11020 _handle = guestfs_create ();
11021 if (_handle == IntPtr.Zero)
11022 throw new Error (\"could not create guestfs handle\");
11025 [DllImport (\"%s\")]
11026 static extern void guestfs_close (IntPtr h);
11030 guestfs_close (_handle);
11033 [DllImport (\"%s\")]
11034 static extern string guestfs_last_error (IntPtr h);
11036 " library library library;
11038 (* Generate C# structure bindings. We prefix struct names with
11039 * underscore because C# cannot have conflicting struct names and
11040 * method names (eg. "class stat" and "stat").
11044 pr " [StructLayout (LayoutKind.Sequential)]\n";
11045 pr " public class _%s {\n" typ;
11048 | name, FChar -> pr " char %s;\n" name
11049 | name, FString -> pr " string %s;\n" name
11051 pr " uint %s_len;\n" name;
11052 pr " string %s;\n" name
11054 pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11055 pr " string %s;\n" name
11056 | name, FUInt32 -> pr " uint %s;\n" name
11057 | name, FInt32 -> pr " int %s;\n" name
11058 | name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
11059 | name, FInt64 -> pr " long %s;\n" name
11060 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
11066 (* Generate C# function bindings. *)
11068 fun (name, style, _, _, _, shortdesc, _) ->
11069 let rec csharp_return_type () =
11070 match fst style with
11072 | RBool n -> "bool"
11074 | RInt64 n -> "long"
11076 | RConstOptString n
11078 | RBufferOut n -> "string"
11079 | RStruct (_,n) -> "_" ^ n
11080 | RHashtable n -> "Hashtable"
11081 | RStringList n -> "string[]"
11082 | RStructList (_,n) -> sprintf "_%s[]" n
11084 and c_return_type () =
11085 match fst style with
11089 | RInt64 _ -> "long"
11091 | RConstOptString _
11093 | RBufferOut _ -> "string"
11094 | RStruct (_,n) -> "_" ^ n
11096 | RStringList _ -> "string[]"
11097 | RStructList (_,n) -> sprintf "_%s[]" n
11099 and c_error_comparison () =
11100 match fst style with
11104 | RInt64 _ -> "== -1"
11106 | RConstOptString _
11112 | RStructList (_,_) -> "== null"
11114 and generate_extern_prototype () =
11115 pr " static extern %s guestfs_%s (IntPtr h"
11116 (c_return_type ()) name;
11119 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11120 | FileIn n | FileOut n
11122 pr ", [In] string %s" n
11123 | StringList n | DeviceList n ->
11124 pr ", [In] string[] %s" n
11134 and generate_public_prototype () =
11135 pr " public %s %s (" (csharp_return_type ()) name;
11136 let comma = ref false in
11138 if !comma then pr ", ";
11143 | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11144 | FileIn n | FileOut n
11146 next (); pr "string %s" n
11147 | StringList n | DeviceList n ->
11148 next (); pr "string[] %s" n
11150 next (); pr "bool %s" n
11152 next (); pr "int %s" n
11154 next (); pr "long %s" n
11158 and generate_call () =
11159 pr "guestfs_%s (_handle" name;
11160 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11164 pr " [DllImport (\"%s\")]\n" library;
11165 generate_extern_prototype ();
11167 pr " /// <summary>\n";
11168 pr " /// %s\n" shortdesc;
11169 pr " /// </summary>\n";
11170 generate_public_prototype ();
11172 pr " %s r;\n" (c_return_type ());
11175 pr " if (r %s)\n" (c_error_comparison ());
11176 pr " throw new Error (guestfs_last_error (_handle));\n";
11177 (match fst style with
11180 pr " return r != 0 ? true : false;\n"
11182 pr " Hashtable rr = new Hashtable ();\n";
11183 pr " for (size_t i = 0; i < r.Length; i += 2)\n";
11184 pr " rr.Add (r[i], r[i+1]);\n";
11186 | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11187 | RString _ | RBufferOut _ | RStruct _ | RStringList _
11193 ) all_functions_sorted;
11199 and generate_bindtests () =
11200 generate_header CStyle LGPLv2plus;
11204 #include <stdlib.h>
11205 #include <inttypes.h>
11206 #include <string.h>
11208 #include \"guestfs.h\"
11209 #include \"guestfs-internal.h\"
11210 #include \"guestfs-internal-actions.h\"
11211 #include \"guestfs_protocol.h\"
11213 #define error guestfs_error
11214 #define safe_calloc guestfs_safe_calloc
11215 #define safe_malloc guestfs_safe_malloc
11218 print_strings (char *const *argv)
11223 for (argc = 0; argv[argc] != NULL; ++argc) {
11224 if (argc > 0) printf (\", \");
11225 printf (\"\\\"%%s\\\"\", argv[argc]);
11230 /* The test0 function prints its parameters to stdout. */
11234 match test_functions with
11235 | [] -> assert false
11236 | test0 :: tests -> test0, tests in
11239 let (name, style, _, _, _, _, _) = test0 in
11240 generate_prototype ~extern:false ~semicolon:false ~newline:true
11241 ~handle:"g" ~prefix:"guestfs__" name style;
11246 | Device n | Dev_or_Path n
11249 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
11253 pr " for (i = 0; i < %s_size; ++i)\n" n;
11254 pr " printf (\"<%%02x>\", %s[i]);\n" n;
11255 pr " printf (\"\\n\");\n";
11257 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11258 | StringList n | DeviceList n -> pr " print_strings (%s);\n" n
11259 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11260 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
11261 | Int64 n -> pr " printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11263 pr " /* Java changes stdout line buffering so we need this: */\n";
11264 pr " fflush (stdout);\n";
11270 fun (name, style, _, _, _, _, _) ->
11271 if String.sub name (String.length name - 3) 3 <> "err" then (
11272 pr "/* Test normal return. */\n";
11273 generate_prototype ~extern:false ~semicolon:false ~newline:true
11274 ~handle:"g" ~prefix:"guestfs__" name style;
11276 (match fst style with
11281 pr " sscanf (val, \"%%d\", &r);\n";
11284 pr " int64_t r;\n";
11285 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
11288 pr " return STREQ (val, \"true\");\n"
11290 | RConstOptString _ ->
11291 (* Can't return the input string here. Return a static
11292 * string so we ensure we get a segfault if the caller
11293 * tries to free it.
11295 pr " return \"static string\";\n"
11297 pr " return strdup (val);\n"
11299 pr " char **strs;\n";
11301 pr " sscanf (val, \"%%d\", &n);\n";
11302 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11303 pr " for (i = 0; i < n; ++i) {\n";
11304 pr " strs[i] = safe_malloc (g, 16);\n";
11305 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
11307 pr " strs[n] = NULL;\n";
11308 pr " return strs;\n"
11309 | RStruct (_, typ) ->
11310 pr " struct guestfs_%s *r;\n" typ;
11311 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11313 | RStructList (_, typ) ->
11314 pr " struct guestfs_%s_list *r;\n" typ;
11315 pr " r = safe_calloc (g, sizeof *r, 1);\n";
11316 pr " sscanf (val, \"%%d\", &r->len);\n";
11317 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11320 pr " char **strs;\n";
11322 pr " sscanf (val, \"%%d\", &n);\n";
11323 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11324 pr " for (i = 0; i < n; ++i) {\n";
11325 pr " strs[i*2] = safe_malloc (g, 16);\n";
11326 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
11327 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
11328 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11330 pr " strs[n*2] = NULL;\n";
11331 pr " return strs;\n"
11333 pr " return strdup (val);\n"
11338 pr "/* Test error return. */\n";
11339 generate_prototype ~extern:false ~semicolon:false ~newline:true
11340 ~handle:"g" ~prefix:"guestfs__" name style;
11342 pr " error (g, \"error\");\n";
11343 (match fst style with
11344 | RErr | RInt _ | RInt64 _ | RBool _ ->
11346 | RConstString _ | RConstOptString _
11347 | RString _ | RStringList _ | RStruct _
11351 pr " return NULL;\n"
11358 and generate_ocaml_bindtests () =
11359 generate_header OCamlStyle GPLv2plus;
11363 let g = Guestfs.create () in
11367 String.concat " " (
11370 | CallString s -> "\"" ^ s ^ "\""
11371 | CallOptString None -> "None"
11372 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11373 | CallStringList xs ->
11374 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11375 | CallInt i when i >= 0 -> string_of_int i
11376 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11377 | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11378 | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11379 | CallBool b -> string_of_bool b
11380 | CallBuffer s -> sprintf "%S" s
11385 generate_lang_bindtests (
11386 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
11389 pr "print_endline \"EOF\"\n"
11391 and generate_perl_bindtests () =
11392 pr "#!/usr/bin/perl -w\n";
11393 generate_header HashStyle GPLv2plus;
11400 my $g = Sys::Guestfs->new ();
11404 String.concat ", " (
11407 | CallString s -> "\"" ^ s ^ "\""
11408 | CallOptString None -> "undef"
11409 | CallOptString (Some s) -> sprintf "\"%s\"" s
11410 | CallStringList xs ->
11411 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11412 | CallInt i -> string_of_int i
11413 | CallInt64 i -> Int64.to_string i
11414 | CallBool b -> if b then "1" else "0"
11415 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11420 generate_lang_bindtests (
11421 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11424 pr "print \"EOF\\n\"\n"
11426 and generate_python_bindtests () =
11427 generate_header HashStyle GPLv2plus;
11432 g = guestfs.GuestFS ()
11436 String.concat ", " (
11439 | CallString s -> "\"" ^ s ^ "\""
11440 | CallOptString None -> "None"
11441 | CallOptString (Some s) -> sprintf "\"%s\"" s
11442 | CallStringList xs ->
11443 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11444 | CallInt i -> string_of_int i
11445 | CallInt64 i -> Int64.to_string i
11446 | CallBool b -> if b then "1" else "0"
11447 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11452 generate_lang_bindtests (
11453 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11456 pr "print \"EOF\"\n"
11458 and generate_ruby_bindtests () =
11459 generate_header HashStyle GPLv2plus;
11464 g = Guestfs::create()
11468 String.concat ", " (
11471 | CallString s -> "\"" ^ s ^ "\""
11472 | CallOptString None -> "nil"
11473 | CallOptString (Some s) -> sprintf "\"%s\"" s
11474 | CallStringList xs ->
11475 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11476 | CallInt i -> string_of_int i
11477 | CallInt64 i -> Int64.to_string i
11478 | CallBool b -> string_of_bool b
11479 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11484 generate_lang_bindtests (
11485 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11488 pr "print \"EOF\\n\"\n"
11490 and generate_java_bindtests () =
11491 generate_header CStyle GPLv2plus;
11494 import com.redhat.et.libguestfs.*;
11496 public class Bindtests {
11497 public static void main (String[] argv)
11500 GuestFS g = new GuestFS ();
11504 String.concat ", " (
11507 | CallString s -> "\"" ^ s ^ "\""
11508 | CallOptString None -> "null"
11509 | CallOptString (Some s) -> sprintf "\"%s\"" s
11510 | CallStringList xs ->
11512 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11513 | CallInt i -> string_of_int i
11514 | CallInt64 i -> Int64.to_string i
11515 | CallBool b -> string_of_bool b
11517 "new byte[] { " ^ String.concat "," (
11518 map_chars (fun c -> string_of_int (Char.code c)) s
11524 generate_lang_bindtests (
11525 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
11529 System.out.println (\"EOF\");
11531 catch (Exception exn) {
11532 System.err.println (exn);
11539 and generate_haskell_bindtests () =
11540 generate_header HaskellStyle GPLv2plus;
11543 module Bindtests where
11544 import qualified Guestfs
11547 g <- Guestfs.create
11551 String.concat " " (
11554 | CallString s -> "\"" ^ s ^ "\""
11555 | CallOptString None -> "Nothing"
11556 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11557 | CallStringList xs ->
11558 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11559 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11560 | CallInt i -> string_of_int i
11561 | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11562 | CallInt64 i -> Int64.to_string i
11563 | CallBool true -> "True"
11564 | CallBool false -> "False"
11565 | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11570 generate_lang_bindtests (
11571 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
11574 pr " putStrLn \"EOF\"\n"
11576 (* Language-independent bindings tests - we do it this way to
11577 * ensure there is parity in testing bindings across all languages.
11579 and generate_lang_bindtests call =
11580 call "test0" [CallString "abc"; CallOptString (Some "def");
11581 CallStringList []; CallBool false;
11582 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11583 CallBuffer "abc\000abc"];
11584 call "test0" [CallString "abc"; CallOptString None;
11585 CallStringList []; CallBool false;
11586 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11587 CallBuffer "abc\000abc"];
11588 call "test0" [CallString ""; CallOptString (Some "def");
11589 CallStringList []; CallBool false;
11590 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11591 CallBuffer "abc\000abc"];
11592 call "test0" [CallString ""; CallOptString (Some "");
11593 CallStringList []; CallBool false;
11594 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11595 CallBuffer "abc\000abc"];
11596 call "test0" [CallString "abc"; CallOptString (Some "def");
11597 CallStringList ["1"]; CallBool false;
11598 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11599 CallBuffer "abc\000abc"];
11600 call "test0" [CallString "abc"; CallOptString (Some "def");
11601 CallStringList ["1"; "2"]; CallBool false;
11602 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11603 CallBuffer "abc\000abc"];
11604 call "test0" [CallString "abc"; CallOptString (Some "def");
11605 CallStringList ["1"]; CallBool true;
11606 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11607 CallBuffer "abc\000abc"];
11608 call "test0" [CallString "abc"; CallOptString (Some "def");
11609 CallStringList ["1"]; CallBool false;
11610 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11611 CallBuffer "abc\000abc"];
11612 call "test0" [CallString "abc"; CallOptString (Some "def");
11613 CallStringList ["1"]; CallBool false;
11614 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11615 CallBuffer "abc\000abc"];
11616 call "test0" [CallString "abc"; CallOptString (Some "def");
11617 CallStringList ["1"]; CallBool false;
11618 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11619 CallBuffer "abc\000abc"];
11620 call "test0" [CallString "abc"; CallOptString (Some "def");
11621 CallStringList ["1"]; CallBool false;
11622 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11623 CallBuffer "abc\000abc"];
11624 call "test0" [CallString "abc"; CallOptString (Some "def");
11625 CallStringList ["1"]; CallBool false;
11626 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11627 CallBuffer "abc\000abc"];
11628 call "test0" [CallString "abc"; CallOptString (Some "def");
11629 CallStringList ["1"]; CallBool false;
11630 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11631 CallBuffer "abc\000abc"]
11633 (* XXX Add here tests of the return and error functions. *)
11635 (* Code to generator bindings for virt-inspector. Currently only
11636 * implemented for OCaml code (for virt-p2v 2.0).
11638 let rng_input = "inspector/virt-inspector.rng"
11640 (* Read the input file and parse it into internal structures. This is
11641 * by no means a complete RELAX NG parser, but is just enough to be
11642 * able to parse the specific input file.
11645 | Element of string * rng list (* <element name=name/> *)
11646 | Attribute of string * rng list (* <attribute name=name/> *)
11647 | Interleave of rng list (* <interleave/> *)
11648 | ZeroOrMore of rng (* <zeroOrMore/> *)
11649 | OneOrMore of rng (* <oneOrMore/> *)
11650 | Optional of rng (* <optional/> *)
11651 | Choice of string list (* <choice><value/>*</choice> *)
11652 | Value of string (* <value>str</value> *)
11653 | Text (* <text/> *)
11655 let rec string_of_rng = function
11656 | Element (name, xs) ->
11657 "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11658 | Attribute (name, xs) ->
11659 "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11660 | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11661 | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11662 | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11663 | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11664 | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11665 | Value value -> "Value \"" ^ value ^ "\""
11668 and string_of_rng_list xs =
11669 String.concat ", " (List.map string_of_rng xs)
11671 let rec parse_rng ?defines context = function
11673 | Xml.Element ("element", ["name", name], children) :: rest ->
11674 Element (name, parse_rng ?defines context children)
11675 :: parse_rng ?defines context rest
11676 | Xml.Element ("attribute", ["name", name], children) :: rest ->
11677 Attribute (name, parse_rng ?defines context children)
11678 :: parse_rng ?defines context rest
11679 | Xml.Element ("interleave", [], children) :: rest ->
11680 Interleave (parse_rng ?defines context children)
11681 :: parse_rng ?defines context rest
11682 | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11683 let rng = parse_rng ?defines context [child] in
11685 | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11687 failwithf "%s: <zeroOrMore> contains more than one child element"
11690 | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11691 let rng = parse_rng ?defines context [child] in
11693 | [child] -> OneOrMore child :: parse_rng ?defines context rest
11695 failwithf "%s: <oneOrMore> contains more than one child element"
11698 | Xml.Element ("optional", [], [child]) :: rest ->
11699 let rng = parse_rng ?defines context [child] in
11701 | [child] -> Optional child :: parse_rng ?defines context rest
11703 failwithf "%s: <optional> contains more than one child element"
11706 | Xml.Element ("choice", [], children) :: rest ->
11707 let values = List.map (
11708 function Xml.Element ("value", [], [Xml.PCData value]) -> value
11710 failwithf "%s: can't handle anything except <value> in <choice>"
11714 :: parse_rng ?defines context rest
11715 | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11716 Value value :: parse_rng ?defines context rest
11717 | Xml.Element ("text", [], []) :: rest ->
11718 Text :: parse_rng ?defines context rest
11719 | Xml.Element ("ref", ["name", name], []) :: rest ->
11720 (* Look up the reference. Because of limitations in this parser,
11721 * we can't handle arbitrarily nested <ref> yet. You can only
11722 * use <ref> from inside <start>.
11724 (match defines with
11726 failwithf "%s: contains <ref>, but no refs are defined yet" context
11728 let rng = StringMap.find name map in
11729 rng @ parse_rng ?defines context rest
11732 failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11735 let xml = Xml.parse_file rng_input in
11737 | Xml.Element ("grammar", _,
11738 Xml.Element ("start", _, gram) :: defines) ->
11739 (* The <define/> elements are referenced in the <start> section,
11740 * so build a map of those first.
11742 let defines = List.fold_left (
11744 function Xml.Element ("define", ["name", name], defn) ->
11745 StringMap.add name defn map
11747 failwithf "%s: expected <define name=name/>" rng_input
11748 ) StringMap.empty defines in
11749 let defines = StringMap.mapi parse_rng defines in
11751 (* Parse the <start> clause, passing the defines. *)
11752 parse_rng ~defines "<start>" gram
11754 failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11757 let name_of_field = function
11758 | Element (name, _) | Attribute (name, _)
11759 | ZeroOrMore (Element (name, _))
11760 | OneOrMore (Element (name, _))
11761 | Optional (Element (name, _)) -> name
11762 | Optional (Attribute (name, _)) -> name
11763 | Text -> (* an unnamed field in an element *)
11766 failwithf "name_of_field failed at: %s" (string_of_rng rng)
11768 (* At the moment this function only generates OCaml types. However we
11769 * should parameterize it later so it can generate types/structs in a
11770 * variety of languages.
11772 let generate_types xs =
11773 (* A simple type is one that can be printed out directly, eg.
11774 * "string option". A complex type is one which has a name and has
11775 * to be defined via another toplevel definition, eg. a struct.
11777 * generate_type generates code for either simple or complex types.
11778 * In the simple case, it returns the string ("string option"). In
11779 * the complex case, it returns the name ("mountpoint"). In the
11780 * complex case it has to print out the definition before returning,
11781 * so it should only be called when we are at the beginning of a
11782 * new line (BOL context).
11784 let rec generate_type = function
11785 | Text -> (* string *)
11787 | Choice values -> (* [`val1|`val2|...] *)
11788 "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11789 | ZeroOrMore rng -> (* <rng> list *)
11790 let t, is_simple = generate_type rng in
11791 t ^ " list (* 0 or more *)", is_simple
11792 | OneOrMore rng -> (* <rng> list *)
11793 let t, is_simple = generate_type rng in
11794 t ^ " list (* 1 or more *)", is_simple
11795 (* virt-inspector hack: bool *)
11796 | Optional (Attribute (name, [Value "1"])) ->
11798 | Optional rng -> (* <rng> list *)
11799 let t, is_simple = generate_type rng in
11800 t ^ " option", is_simple
11801 (* type name = { fields ... } *)
11802 | Element (name, fields) when is_attrs_interleave fields ->
11803 generate_type_struct name (get_attrs_interleave fields)
11804 | Element (name, [field]) (* type name = field *)
11805 | Attribute (name, [field]) ->
11806 let t, is_simple = generate_type field in
11807 if is_simple then (t, true)
11809 pr "type %s = %s\n" name t;
11812 | Element (name, fields) -> (* type name = { fields ... } *)
11813 generate_type_struct name fields
11815 failwithf "generate_type failed at: %s" (string_of_rng rng)
11817 and is_attrs_interleave = function
11818 | [Interleave _] -> true
11819 | Attribute _ :: fields -> is_attrs_interleave fields
11820 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11823 and get_attrs_interleave = function
11824 | [Interleave fields] -> fields
11825 | ((Attribute _) as field) :: fields
11826 | ((Optional (Attribute _)) as field) :: fields ->
11827 field :: get_attrs_interleave fields
11828 | _ -> assert false
11830 and generate_types xs =
11831 List.iter (fun x -> ignore (generate_type x)) xs
11833 and generate_type_struct name fields =
11834 (* Calculate the types of the fields first. We have to do this
11835 * before printing anything so we are still in BOL context.
11837 let types = List.map fst (List.map generate_type fields) in
11839 (* Special case of a struct containing just a string and another
11840 * field. Turn it into an assoc list.
11843 | ["string"; other] ->
11844 let fname1, fname2 =
11846 | [f1; f2] -> name_of_field f1, name_of_field f2
11847 | _ -> assert false in
11848 pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11852 pr "type %s = {\n" name;
11854 fun (field, ftype) ->
11855 let fname = name_of_field field in
11856 pr " %s_%s : %s;\n" name fname ftype
11857 ) (List.combine fields types);
11859 (* Return the name of this type, and
11860 * false because it's not a simple type.
11867 let generate_parsers xs =
11868 (* As for generate_type above, generate_parser makes a parser for
11869 * some type, and returns the name of the parser it has generated.
11870 * Because it (may) need to print something, it should always be
11871 * called in BOL context.
11873 let rec generate_parser = function
11874 | Text -> (* string *)
11875 "string_child_or_empty"
11876 | Choice values -> (* [`val1|`val2|...] *)
11877 sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11879 (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11880 | ZeroOrMore rng -> (* <rng> list *)
11881 let pa = generate_parser rng in
11882 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11883 | OneOrMore rng -> (* <rng> list *)
11884 let pa = generate_parser rng in
11885 sprintf "(fun x -> List.map %s (Xml.children x))" pa
11886 (* virt-inspector hack: bool *)
11887 | Optional (Attribute (name, [Value "1"])) ->
11888 sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11889 | Optional rng -> (* <rng> list *)
11890 let pa = generate_parser rng in
11891 sprintf "(function None -> None | Some x -> Some (%s x))" pa
11892 (* type name = { fields ... } *)
11893 | Element (name, fields) when is_attrs_interleave fields ->
11894 generate_parser_struct name (get_attrs_interleave fields)
11895 | Element (name, [field]) -> (* type name = field *)
11896 let pa = generate_parser field in
11897 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11898 pr "let %s =\n" parser_name;
11900 pr "let parse_%s = %s\n" name parser_name;
11902 | Attribute (name, [field]) ->
11903 let pa = generate_parser field in
11904 let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11905 pr "let %s =\n" parser_name;
11907 pr "let parse_%s = %s\n" name parser_name;
11909 | Element (name, fields) -> (* type name = { fields ... } *)
11910 generate_parser_struct name ([], fields)
11912 failwithf "generate_parser failed at: %s" (string_of_rng rng)
11914 and is_attrs_interleave = function
11915 | [Interleave _] -> true
11916 | Attribute _ :: fields -> is_attrs_interleave fields
11917 | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11920 and get_attrs_interleave = function
11921 | [Interleave fields] -> [], fields
11922 | ((Attribute _) as field) :: fields
11923 | ((Optional (Attribute _)) as field) :: fields ->
11924 let attrs, interleaves = get_attrs_interleave fields in
11925 (field :: attrs), interleaves
11926 | _ -> assert false
11928 and generate_parsers xs =
11929 List.iter (fun x -> ignore (generate_parser x)) xs
11931 and generate_parser_struct name (attrs, interleaves) =
11932 (* Generate parsers for the fields first. We have to do this
11933 * before printing anything so we are still in BOL context.
11935 let fields = attrs @ interleaves in
11936 let pas = List.map generate_parser fields in
11938 (* Generate an intermediate tuple from all the fields first.
11939 * If the type is just a string + another field, then we will
11940 * return this directly, otherwise it is turned into a record.
11942 * RELAX NG note: This code treats <interleave> and plain lists of
11943 * fields the same. In other words, it doesn't bother enforcing
11944 * any ordering of fields in the XML.
11946 pr "let parse_%s x =\n" name;
11947 pr " let t = (\n ";
11948 let comma = ref false in
11951 if !comma then pr ",\n ";
11954 | Optional (Attribute (fname, [field])), pa ->
11956 | Optional (Element (fname, [field])), pa ->
11957 pr "%s (optional_child %S x)" pa fname
11958 | Attribute (fname, [Text]), _ ->
11959 pr "attribute %S x" fname
11960 | (ZeroOrMore _ | OneOrMore _), pa ->
11965 let fname = name_of_field field in
11966 pr "%s (child %S x)" pa fname
11967 ) (List.combine fields pas);
11971 | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11975 pr " (Obj.magic t : %s)\n" name
11979 | (Optional (Attribute (fname, [field])), pa) ->
11980 pr " %s_%s =\n" name fname;
11982 | (Optional (Element (fname, [field])), pa) ->
11983 pr " %s_%s =\n" name fname;
11984 pr " (let x = optional_child %S x in\n" fname;
11987 let fname = name_of_field field in
11988 pr " %s_%s =\n" name fname;
11989 pr " (let x = child %S x in\n" fname;
11991 ) (List.combine fields pas);
11995 sprintf "parse_%s" name
11998 generate_parsers xs
12000 (* Generate ocaml/guestfs_inspector.mli. *)
12001 let generate_ocaml_inspector_mli () =
12002 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12005 (** This is an OCaml language binding to the external [virt-inspector]
12008 For more information, please read the man page [virt-inspector(1)].
12013 generate_types grammar;
12014 pr "(** The nested information returned from the {!inspect} function. *)\n";
12018 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12019 (** To inspect a libvirt domain called [name], pass a singleton
12020 list: [inspect [name]]. When using libvirt only, you may
12021 optionally pass a libvirt URI using [inspect ~connect:uri ...].
12023 To inspect a disk image or images, pass a list of the filenames
12024 of the disk images: [inspect filenames]
12026 This function inspects the given guest or disk images and
12027 returns a list of operating system(s) found and a large amount
12028 of information about them. In the vast majority of cases,
12029 a virtual machine only contains a single operating system.
12031 If the optional [~xml] parameter is given, then this function
12032 skips running the external virt-inspector program and just
12033 parses the given XML directly (which is expected to be XML
12034 produced from a previous run of virt-inspector). The list of
12035 names and connect URI are ignored in this case.
12037 This function can throw a wide variety of exceptions, for example
12038 if the external virt-inspector program cannot be found, or if
12039 it doesn't generate valid XML.
12043 (* Generate ocaml/guestfs_inspector.ml. *)
12044 let generate_ocaml_inspector_ml () =
12045 generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12050 generate_types grammar;
12054 (* Misc functions which are used by the parser code below. *)
12055 let first_child = function
12056 | Xml.Element (_, _, c::_) -> c
12057 | Xml.Element (name, _, []) ->
12058 failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12059 | Xml.PCData str ->
12060 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12062 let string_child_or_empty = function
12063 | Xml.Element (_, _, [Xml.PCData s]) -> s
12064 | Xml.Element (_, _, []) -> \"\"
12065 | Xml.Element (x, _, _) ->
12066 failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12068 | Xml.PCData str ->
12069 failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12071 let optional_child name xml =
12072 let children = Xml.children xml in
12074 Some (List.find (function
12075 | Xml.Element (n, _, _) when n = name -> true
12076 | _ -> false) children)
12080 let child name xml =
12081 match optional_child name xml with
12084 failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12086 let attribute name xml =
12087 try Xml.attrib xml name
12088 with Xml.No_attribute _ ->
12089 failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12093 generate_parsers grammar;
12097 (* Run external virt-inspector, then use parser to parse the XML. *)
12098 let inspect ?connect ?xml names =
12102 if names = [] then invalid_arg \"inspect: no names given\";
12103 let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12104 (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12106 let cmd = List.map Filename.quote cmd in
12107 let cmd = String.concat \" \" cmd in
12108 let chan = open_process_in cmd in
12109 let xml = Xml.parse_in chan in
12110 (match close_process_in chan with
12112 | WEXITED _ -> failwith \"external virt-inspector command failed\"
12113 | WSIGNALED i | WSTOPPED i ->
12114 failwith (\"external virt-inspector command died or stopped on sig \" ^
12119 Xml.parse_string doc in
12120 parse_operatingsystems xml
12123 and generate_max_proc_nr () =
12124 pr "%d\n" max_proc_nr
12126 let output_to filename k =
12127 let filename_new = filename ^ ".new" in
12128 chan := open_out filename_new;
12131 chan := Pervasives.stdout;
12133 (* Is the new file different from the current file? *)
12134 if Sys.file_exists filename && files_equal filename filename_new then
12135 unlink filename_new (* same, so skip it *)
12137 (* different, overwrite old one *)
12138 (try chmod filename 0o644 with Unix_error _ -> ());
12139 rename filename_new filename;
12140 chmod filename 0o444;
12141 printf "written %s\n%!" filename;
12144 let perror msg = function
12145 | Unix_error (err, _, _) ->
12146 eprintf "%s: %s\n" msg (error_message err)
12148 eprintf "%s: %s\n" msg (Printexc.to_string exn)
12150 (* Main program. *)
12153 try openfile "HACKING" [O_RDWR] 0
12155 | Unix_error (ENOENT, _, _) ->
12157 You are probably running this from the wrong directory.
12158 Run it from the top source directory using the command
12163 perror "open: HACKING" exn;
12166 (* Acquire a lock so parallel builds won't try to run the generator
12167 * twice at the same time. Subsequent builds will wait for the first
12168 * one to finish. Note the lock is released implicitly when the
12171 (try lockf lock_fd F_LOCK 1
12173 perror "lock: HACKING" exn;
12176 check_functions ();
12178 output_to "src/guestfs_protocol.x" generate_xdr;
12179 output_to "src/guestfs-structs.h" generate_structs_h;
12180 output_to "src/guestfs-actions.h" generate_actions_h;
12181 output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12182 output_to "src/guestfs-actions.c" generate_client_actions;
12183 output_to "src/guestfs-bindtests.c" generate_bindtests;
12184 output_to "src/guestfs-structs.pod" generate_structs_pod;
12185 output_to "src/guestfs-actions.pod" generate_actions_pod;
12186 output_to "src/guestfs-availability.pod" generate_availability_pod;
12187 output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12188 output_to "src/libguestfs.syms" generate_linker_script;
12189 output_to "daemon/actions.h" generate_daemon_actions_h;
12190 output_to "daemon/stubs.c" generate_daemon_actions;
12191 output_to "daemon/names.c" generate_daemon_names;
12192 output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12193 output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12194 output_to "capitests/tests.c" generate_tests;
12195 output_to "fish/cmds.c" generate_fish_cmds;
12196 output_to "fish/completion.c" generate_fish_completion;
12197 output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12198 output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12199 output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12200 output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12201 output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12202 output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12203 output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12204 output_to "perl/Guestfs.xs" generate_perl_xs;
12205 output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12206 output_to "perl/bindtests.pl" generate_perl_bindtests;
12207 output_to "python/guestfs-py.c" generate_python_c;
12208 output_to "python/guestfs.py" generate_python_py;
12209 output_to "python/bindtests.py" generate_python_bindtests;
12210 output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12211 output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12212 output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12216 let cols = cols_of_struct typ in
12217 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12218 output_to filename (generate_java_struct jtyp cols);
12221 output_to "java/Makefile.inc" generate_java_makefile_inc;
12222 output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12223 output_to "java/Bindtests.java" generate_java_bindtests;
12224 output_to "haskell/Guestfs.hs" generate_haskell_hs;
12225 output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12226 output_to "csharp/Libguestfs.cs" generate_csharp;
12228 (* Always generate this file last, and unconditionally. It's used
12229 * by the Makefile to know when we must re-run the generator.
12231 let chan = open_out "src/stamp-generator" in
12232 fprintf chan "1\n";
12235 printf "generated %d lines of code\n" !lines