3 * Copyright (C) 2009 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 below), and
25 * daemon/<somefile>.c to write the implementation.
27 * After editing this file, run it (./src/generator.ml) to regenerate all the
28 * output files. Note that if you are using a separate build directory you
29 * must run generator.ml from the _source_ directory.
31 * IMPORTANT: This script should NOT print any warnings. If it prints
32 * warnings, you should treat them as errors.
40 type style = ret * args
42 (* "RErr" as a return value means an int used as a simple error
43 * indication, ie. 0 or -1.
47 (* "RInt" as a return value means an int which is -1 for error
48 * or any value >= 0 on success. Only use this for smallish
49 * positive ints (0 <= i < 2^30).
53 (* "RInt64" is the same as RInt, but is guaranteed to be able
54 * to return a full 64 bit value, _except_ that -1 means error
55 * (so -1 cannot be a valid, non-error return value).
59 (* "RBool" is a bool return value which can be true/false or
64 (* "RConstString" is a string that refers to a constant value.
65 * The return value must NOT be NULL (since NULL indicates
68 * Try to avoid using this. In particular you cannot use this
69 * for values returned from the daemon, because there is no
70 * thread-safe way to return them in the C API.
72 | RConstString of string
74 (* "RConstOptString" is an even more broken version of
75 * "RConstString". The returned string may be NULL and there
76 * is no way to return an error indication. Avoid using this!
78 | RConstOptString of string
80 (* "RString" is a returned string. It must NOT be NULL, since
81 * a NULL return indicates an error. The caller frees this.
85 (* "RStringList" is a list of strings. No string in the list
86 * can be NULL. The caller frees the strings and the array.
88 | RStringList of string
90 (* "RStruct" is a function which returns a single named structure
91 * or an error indication (in C, a struct, and in other languages
92 * with varying representations, but usually very efficient). See
93 * after the function list below for the structures.
95 | RStruct of string * string (* name of retval, name of struct *)
97 (* "RStructList" is a function which returns either a list/array
98 * of structures (could be zero-length), or an error indication.
100 | RStructList of string * string (* name of retval, name of struct *)
102 (* Key-value pairs of untyped strings. Turns into a hashtable or
103 * dictionary in languages which support it. DON'T use this as a
104 * general "bucket" for results. Prefer a stronger typed return
105 * value if one is available, or write a custom struct. Don't use
106 * this if the list could potentially be very long, since it is
107 * inefficient. Keys should be unique. NULLs are not permitted.
109 | RHashtable of string
111 (* "RBufferOut" is handled almost exactly like RString, but
112 * it allows the string to contain arbitrary 8 bit data including
113 * ASCII NUL. In the C API this causes an implicit extra parameter
114 * to be added of type <size_t *size_r>. The extra parameter
115 * returns the actual size of the return buffer in bytes.
117 * Other programming languages support strings with arbitrary 8 bit
120 * At the RPC layer we have to use the opaque<> type instead of
121 * string<>. Returned data is still limited to the max message
124 | RBufferOut of string
126 and args = argt list (* Function parameters, guestfs handle is implicit. *)
128 (* Note in future we should allow a "variable args" parameter as
129 * the final parameter, to allow commands like
130 * chmod mode file [file(s)...]
131 * This is not implemented yet, but many commands (such as chmod)
132 * are currently defined with the argument order keeping this future
133 * possibility in mind.
136 | String of string (* const char *name, cannot be NULL *)
137 | Device of string (* /dev device name, cannot be NULL *)
138 | Pathname of string (* file name, cannot be NULL *)
139 | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140 | OptString of string (* const char *name, may be NULL *)
141 | StringList of string(* list of strings (each string cannot be NULL) *)
142 | Bool of string (* boolean *)
143 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
144 (* These are treated as filenames (simple string parameters) in
145 * the C API and bindings. But in the RPC protocol, we transfer
146 * the actual file content up to or down from the daemon.
147 * FileIn: local machine -> daemon (in request)
148 * FileOut: daemon -> local machine (in reply)
149 * In guestfish (only), the special name "-" means read from
150 * stdin or write to stdout.
155 (* Opaque buffer which can contain arbitrary 8 bit data.
156 * In the C API, this is expressed as <char *, int> pair.
157 * Most other languages have a string type which can contain
158 * ASCII NUL. We use whatever type is appropriate for each
160 * Buffers are limited by the total message size. To transfer
161 * large blocks of data, use FileIn/FileOut parameters instead.
162 * To return an arbitrary buffer, use RBufferOut.
168 | ProtocolLimitWarning (* display warning about protocol size limits *)
169 | DangerWillRobinson (* flags particularly dangerous commands *)
170 | FishAlias of string (* provide an alias for this cmd in guestfish *)
171 | FishAction of string (* call this function in guestfish *)
172 | NotInFish (* do not export via guestfish *)
173 | NotInDocs (* do not add this function to documentation *)
174 | DeprecatedBy of string (* function is deprecated, use .. instead *)
176 (* You can supply zero or as many tests as you want per API call.
178 * Note that the test environment has 3 block devices, of size 500MB,
179 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
180 * a fourth squashfs block device with some known files on it (/dev/sdd).
182 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
183 * Number of cylinders was 63 for IDE emulated disks with precisely
184 * the same size. How exactly this is calculated is a mystery.
186 * The squashfs block device (/dev/sdd) comes from images/test.sqsh.
188 * To be able to run the tests in a reasonable amount of time,
189 * the virtual machine and block devices are reused between tests.
190 * So don't try testing kill_subprocess :-x
192 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194 * Don't assume anything about the previous contents of the block
195 * devices. Use 'Init*' to create some initial scenarios.
197 * You can add a prerequisite clause to any individual test. This
198 * is a run-time check, which, if it fails, causes the test to be
199 * skipped. Useful if testing a command which might not work on
200 * all variations of libguestfs builds. A test that has prerequisite
201 * of 'Always' is run unconditionally.
203 * In addition, packagers can skip individual tests by setting the
204 * environment variables: eg:
205 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
206 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
208 type tests = (test_init * test_prereq * test) list
210 (* Run the command sequence and just expect nothing to fail. *)
213 (* Run the command sequence and expect the output of the final
214 * command to be the string.
216 | TestOutput of seq * string
218 (* Run the command sequence and expect the output of the final
219 * command to be the list of strings.
221 | TestOutputList of seq * string list
223 (* Run the command sequence and expect the output of the final
224 * command to be the list of block devices (could be either
225 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
226 * character of each string).
228 | TestOutputListOfDevices of seq * string list
230 (* Run the command sequence and expect the output of the final
231 * command to be the integer.
233 | TestOutputInt of seq * int
235 (* Run the command sequence and expect the output of the final
236 * command to be <op> <int>, eg. ">=", "1".
238 | TestOutputIntOp of seq * string * int
240 (* Run the command sequence and expect the output of the final
241 * command to be a true value (!= 0 or != NULL).
243 | TestOutputTrue of seq
245 (* Run the command sequence and expect the output of the final
246 * command to be a false value (== 0 or == NULL, but not an error).
248 | TestOutputFalse of seq
250 (* Run the command sequence and expect the output of the final
251 * command to be a list of the given length (but don't care about
254 | TestOutputLength of seq * int
256 (* Run the command sequence and expect the output of the final
257 * command to be a buffer (RBufferOut), ie. string + size.
259 | TestOutputBuffer of seq * string
261 (* Run the command sequence and expect the output of the final
262 * command to be a structure.
264 | TestOutputStruct of seq * test_field_compare list
266 (* Run the command sequence and expect the final command (only)
269 | TestLastFail of seq
271 and test_field_compare =
272 | CompareWithInt of string * int
273 | CompareWithIntOp of string * string * int
274 | CompareWithString of string * string
275 | CompareFieldsIntEq of string * string
276 | CompareFieldsStrEq of string * string
278 (* Test prerequisites. *)
280 (* Test always runs. *)
283 (* Test is currently disabled - eg. it fails, or it tests some
284 * unimplemented feature.
288 (* 'string' is some C code (a function body) that should return
289 * true or false. The test will run if the code returns true.
293 (* As for 'If' but the test runs _unless_ the code returns true. *)
296 (* Some initial scenarios for testing. *)
298 (* Do nothing, block devices could contain random stuff including
299 * LVM PVs, and some filesystems might be mounted. This is usually
304 (* Block devices are empty and no filesystems are mounted. *)
307 (* /dev/sda contains a single partition /dev/sda1, with random
308 * content. /dev/sdb and /dev/sdc may have random content.
313 (* /dev/sda contains a single partition /dev/sda1, which is formatted
314 * as ext2, empty [except for lost+found] and mounted on /.
315 * /dev/sdb and /dev/sdc may have random content.
321 * /dev/sda1 (is a PV):
322 * /dev/VG/LV (size 8MB):
323 * formatted as ext2, empty [except for lost+found], mounted on /
324 * /dev/sdb and /dev/sdc may have random content.
328 (* /dev/sdd (the squashfs, see images/ directory in source)
333 (* Sequence of commands for testing. *)
335 and cmd = string list
337 (* Note about long descriptions: When referring to another
338 * action, use the format C<guestfs_other> (ie. the full name of
339 * the C function). This will be replaced as appropriate in other
342 * Apart from that, long descriptions are just perldoc paragraphs.
345 (* Generate a random UUID (used in tests). *)
347 let chan = Unix.open_process_in "uuidgen" in
348 let uuid = input_line chan in
349 (match Unix.close_process_in chan with
350 | Unix.WEXITED 0 -> ()
352 failwith "uuidgen: process exited with non-zero status"
353 | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
354 failwith "uuidgen: process signalled or stopped by signal"
358 (* These test functions are used in the language binding tests. *)
360 let test_all_args = [
363 StringList "strlist";
370 let test_all_rets = [
371 (* except for RErr, which is tested thoroughly elsewhere *)
372 "test0rint", RInt "valout";
373 "test0rint64", RInt64 "valout";
374 "test0rbool", RBool "valout";
375 "test0rconststring", RConstString "valout";
376 "test0rconstoptstring", RConstOptString "valout";
377 "test0rstring", RString "valout";
378 "test0rstringlist", RStringList "valout";
379 "test0rstruct", RStruct ("valout", "lvm_pv");
380 "test0rstructlist", RStructList ("valout", "lvm_pv");
381 "test0rhashtable", RHashtable "valout";
384 let test_functions = [
385 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387 "internal test function - do not use",
389 This is an internal test function which is used to test whether
390 the automatically generated bindings can handle every possible
391 parameter type correctly.
393 It echos the contents of each parameter to stdout.
395 You probably don't want to call this function.");
399 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401 "internal test function - do not use",
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 return type correctly.
407 It converts string C<val> to the return type.
409 You probably don't want to call this function.");
410 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412 "internal test function - do not use",
414 This is an internal test function which is used to test whether
415 the automatically generated bindings can handle every possible
416 return type correctly.
418 This function always returns an error.
420 You probably don't want to call this function.")]
424 (* non_daemon_functions are any functions which don't get processed
425 * in the daemon, eg. functions for setting and getting local
426 * configuration values.
429 let non_daemon_functions = test_functions @ [
430 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432 "launch the qemu subprocess",
434 Internally libguestfs is implemented by running a virtual machine
437 You should call this after configuring the handle
438 (eg. adding drives) but before performing any actions.");
440 ("wait_ready", (RErr, []), -1, [NotInFish],
442 "wait until the qemu subprocess launches",
444 Internally libguestfs is implemented by running a virtual machine
447 You should call this after C<guestfs_launch> to wait for the launch
450 ("kill_subprocess", (RErr, []), -1, [],
452 "kill the qemu subprocess",
454 This kills the qemu subprocess. You should never need to call this.");
456 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
458 "add an image to examine or modify",
460 This function adds a virtual machine disk image C<filename> to the
461 guest. The first time you call this function, the disk appears as IDE
462 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
465 You don't necessarily need to be root when using libguestfs. However
466 you obviously do need sufficient permissions to access the filename
467 for whatever operations you want to perform (ie. read access if you
468 just want to read the image or write access if you want to modify the
471 This is equivalent to the qemu parameter
472 C<-drive file=filename,cache=off,if=...>.
473 C<cache=off> is omitted in cases where it is not supported by
474 the underlying filesystem.
476 Note that this call checks for the existence of C<filename>. This
477 stops you from specifying other types of drive which are supported
478 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
479 the general C<guestfs_config> call instead.");
481 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
483 "add a CD-ROM disk image to examine",
485 This function adds a virtual CD-ROM disk image to the guest.
487 This is equivalent to the qemu parameter C<-cdrom filename>.
489 Note that this call checks for the existence of C<filename>. This
490 stops you from specifying other types of drive which are supported
491 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
492 the general C<guestfs_config> call instead.");
494 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
496 "add a drive in snapshot mode (read-only)",
498 This adds a drive in snapshot mode, making it effectively
501 Note that writes to the device are allowed, and will be seen for
502 the duration of the guestfs handle, but they are written
503 to a temporary file which is discarded as soon as the guestfs
504 handle is closed. We don't currently have any method to enable
505 changes to be committed, although qemu can support this.
507 This is equivalent to the qemu parameter
508 C<-drive file=filename,snapshot=on,if=...>.
510 Note that this call checks for the existence of C<filename>. This
511 stops you from specifying other types of drive which are supported
512 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
513 the general C<guestfs_config> call instead.");
515 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
517 "add qemu parameters",
519 This can be used to add arbitrary qemu command line parameters
520 of the form C<-param value>. Actually it's not quite arbitrary - we
521 prevent you from setting some parameters which would interfere with
522 parameters that we use.
524 The first character of C<param> string must be a C<-> (dash).
526 C<value> can be NULL.");
528 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
530 "set the qemu binary",
532 Set the qemu binary that we will use.
534 The default is chosen when the library was compiled by the
537 You can also override this by setting the C<LIBGUESTFS_QEMU>
538 environment variable.
540 Setting C<qemu> to C<NULL> restores the default qemu binary.");
542 ("get_qemu", (RConstString "qemu", []), -1, [],
543 [InitNone, Always, TestRun (
545 "get the qemu binary",
547 Return the current qemu binary.
549 This is always non-NULL. If it wasn't set already, then this will
550 return the default qemu binary name.");
552 ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
554 "set the search path",
556 Set the path that libguestfs searches for kernel and initrd.img.
558 The default is C<$libdir/guestfs> unless overridden by setting
559 C<LIBGUESTFS_PATH> environment variable.
561 Setting C<path> to C<NULL> restores the default path.");
563 ("get_path", (RConstString "path", []), -1, [],
564 [InitNone, Always, TestRun (
566 "get the search path",
568 Return the current search path.
570 This is always non-NULL. If it wasn't set already, then this will
571 return the default path.");
573 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
575 "add options to kernel command line",
577 This function is used to add additional options to the
578 guest kernel command line.
580 The default is C<NULL> unless overridden by setting
581 C<LIBGUESTFS_APPEND> environment variable.
583 Setting C<append> to C<NULL> means I<no> additional options
584 are passed (libguestfs always adds a few of its own).");
586 ("get_append", (RConstOptString "append", []), -1, [],
587 (* This cannot be tested with the current framework. The
588 * function can return NULL in normal operations, which the
589 * test framework interprets as an error.
592 "get the additional kernel options",
594 Return the additional kernel options which are added to the
595 guest kernel command line.
597 If C<NULL> then no options are added.");
599 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
603 If C<autosync> is true, this enables autosync. Libguestfs will make a
604 best effort attempt to run C<guestfs_umount_all> followed by
605 C<guestfs_sync> when the handle is closed
606 (also if the program exits without closing handles).
608 This is disabled by default (except in guestfish where it is
609 enabled by default).");
611 ("get_autosync", (RBool "autosync", []), -1, [],
612 [InitNone, Always, TestRun (
613 [["get_autosync"]])],
616 Get the autosync flag.");
618 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
622 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
624 Verbose messages are disabled unless the environment variable
625 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
627 ("get_verbose", (RBool "verbose", []), -1, [],
631 This returns the verbose messages flag.");
633 ("is_ready", (RBool "ready", []), -1, [],
634 [InitNone, Always, TestOutputTrue (
636 "is ready to accept commands",
638 This returns true iff this handle is ready to accept commands
639 (in the C<READY> state).
641 For more information on states, see L<guestfs(3)>.");
643 ("is_config", (RBool "config", []), -1, [],
644 [InitNone, Always, TestOutputFalse (
646 "is in configuration state",
648 This returns true iff this handle is being configured
649 (in the C<CONFIG> state).
651 For more information on states, see L<guestfs(3)>.");
653 ("is_launching", (RBool "launching", []), -1, [],
654 [InitNone, Always, TestOutputFalse (
655 [["is_launching"]])],
656 "is launching subprocess",
658 This returns true iff this handle is launching the subprocess
659 (in the C<LAUNCHING> state).
661 For more information on states, see L<guestfs(3)>.");
663 ("is_busy", (RBool "busy", []), -1, [],
664 [InitNone, Always, TestOutputFalse (
666 "is busy processing a command",
668 This returns true iff this handle is busy processing a command
669 (in the C<BUSY> state).
671 For more information on states, see L<guestfs(3)>.");
673 ("get_state", (RInt "state", []), -1, [],
675 "get the current state",
677 This returns the current state as an opaque integer. This is
678 only useful for printing debug and internal error messages.
680 For more information on states, see L<guestfs(3)>.");
682 ("set_busy", (RErr, []), -1, [NotInFish],
686 This sets the state to C<BUSY>. This is only used when implementing
687 actions using the low-level API.
689 For more information on states, see L<guestfs(3)>.");
691 ("set_ready", (RErr, []), -1, [NotInFish],
693 "set state to ready",
695 This sets the state to C<READY>. This is only used when implementing
696 actions using the low-level API.
698 For more information on states, see L<guestfs(3)>.");
700 ("end_busy", (RErr, []), -1, [NotInFish],
702 "leave the busy state",
704 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
705 state as is. This is only used when implementing
706 actions using the low-level API.
708 For more information on states, see L<guestfs(3)>.");
710 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
711 [InitNone, Always, TestOutputInt (
712 [["set_memsize"; "500"];
713 ["get_memsize"]], 500)],
714 "set memory allocated to the qemu subprocess",
716 This sets the memory size in megabytes allocated to the
717 qemu subprocess. This only has any effect if called before
720 You can also change this by setting the environment
721 variable C<LIBGUESTFS_MEMSIZE> before the handle is
724 For more information on the architecture of libguestfs,
725 see L<guestfs(3)>.");
727 ("get_memsize", (RInt "memsize", []), -1, [],
728 [InitNone, Always, TestOutputIntOp (
729 [["get_memsize"]], ">=", 256)],
730 "get memory allocated to the qemu subprocess",
732 This gets the memory size in megabytes allocated to the
735 If C<guestfs_set_memsize> was not called
736 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
737 then this returns the compiled-in default value for memsize.
739 For more information on the architecture of libguestfs,
740 see L<guestfs(3)>.");
742 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
743 [InitNone, Always, TestOutputIntOp (
744 [["get_pid"]], ">=", 1)],
745 "get PID of qemu subprocess",
747 Return the process ID of the qemu subprocess. If there is no
748 qemu subprocess, then this will return an error.
750 This is an internal call used for debugging and testing.");
752 ("version", (RStruct ("version", "version"), []), -1, [],
753 [InitNone, Always, TestOutputStruct (
754 [["version"]], [CompareWithInt ("major", 1)])],
755 "get the library version number",
757 Return the libguestfs version number that the program is linked
760 Note that because of dynamic linking this is not necessarily
761 the version of libguestfs that you compiled against. You can
762 compile the program, and then at runtime dynamically link
763 against a completely different C<libguestfs.so> library.
765 This call was added in version C<1.0.58>. In previous
766 versions of libguestfs there was no way to get the version
767 number. From C code you can use ELF weak linking tricks to find out if
768 this symbol exists (if it doesn't, then it's an earlier version).
770 The call returns a structure with four elements. The first
771 three (C<major>, C<minor> and C<release>) are numbers and
772 correspond to the usual version triplet. The fourth element
773 (C<extra>) is a string and is normally empty, but may be
774 used for distro-specific information.
776 To construct the original version string:
777 C<$major.$minor.$release$extra>
779 I<Note:> Don't use this call to test for availability
780 of features. Distro backports makes this unreliable.");
782 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
783 [InitNone, Always, TestOutputTrue (
784 [["set_selinux"; "true"];
786 "set SELinux enabled or disabled at appliance boot",
788 This sets the selinux flag that is passed to the appliance
789 at boot time. The default is C<selinux=0> (disabled).
791 Note that if SELinux is enabled, it is always in
792 Permissive mode (C<enforcing=0>).
794 For more information on the architecture of libguestfs,
795 see L<guestfs(3)>.");
797 ("get_selinux", (RBool "selinux", []), -1, [],
799 "get SELinux enabled flag",
801 This returns the current setting of the selinux flag which
802 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
804 For more information on the architecture of libguestfs,
805 see L<guestfs(3)>.");
809 (* daemon_functions are any functions which cause some action
810 * to take place in the daemon.
813 let daemon_functions = [
814 ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
815 [InitEmpty, Always, TestOutput (
816 [["sfdiskM"; "/dev/sda"; ","];
817 ["mkfs"; "ext2"; "/dev/sda1"];
818 ["mount"; "/dev/sda1"; "/"];
819 ["write_file"; "/new"; "new file contents"; "0"];
820 ["cat"; "/new"]], "new file contents")],
821 "mount a guest disk at a position in the filesystem",
823 Mount a guest disk at a position in the filesystem. Block devices
824 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
825 the guest. If those block devices contain partitions, they will have
826 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
829 The rules are the same as for L<mount(2)>: A filesystem must
830 first be mounted on C</> before others can be mounted. Other
831 filesystems can only be mounted on directories which already
834 The mounted filesystem is writable, if we have sufficient permissions
835 on the underlying device.
837 The filesystem options C<sync> and C<noatime> are set with this
838 call, in order to improve reliability.");
840 ("sync", (RErr, []), 2, [],
841 [ InitEmpty, Always, TestRun [["sync"]]],
842 "sync disks, writes are flushed through to the disk image",
844 This syncs the disk, so that any writes are flushed through to the
845 underlying disk image.
847 You should always call this if you have modified a disk image, before
848 closing the handle.");
850 ("touch", (RErr, [Pathname "path"]), 3, [],
851 [InitBasicFS, Always, TestOutputTrue (
853 ["exists"; "/new"]])],
854 "update file timestamps or create a new file",
856 Touch acts like the L<touch(1)> command. It can be used to
857 update the timestamps on a file, or, if the file does not exist,
858 to create a new zero-length file.");
860 ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
861 [InitSquashFS, Always, TestOutput (
862 [["cat"; "/known-2"]], "abcdef\n")],
863 "list the contents of a file",
865 Return the contents of the file named C<path>.
867 Note that this function cannot correctly handle binary files
868 (specifically, files containing C<\\0> character which is treated
869 as end of string). For those you need to use the C<guestfs_read_file>
870 or C<guestfs_download> functions which have a more complex interface.");
872 ("ll", (RString "listing", [Pathname "directory"]), 5, [],
873 [], (* XXX Tricky to test because it depends on the exact format
874 * of the 'ls -l' command, which changes between F10 and F11.
876 "list the files in a directory (long format)",
878 List the files in C<directory> (relative to the root directory,
879 there is no cwd) in the format of 'ls -la'.
881 This command is mostly useful for interactive sessions. It
882 is I<not> intended that you try to parse the output string.");
884 ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
885 [InitBasicFS, Always, TestOutputList (
888 ["touch"; "/newest"];
889 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
890 "list the files in a directory",
892 List the files in C<directory> (relative to the root directory,
893 there is no cwd). The '.' and '..' entries are not returned, but
894 hidden files are shown.
896 This command is mostly useful for interactive sessions. Programs
897 should probably use C<guestfs_readdir> instead.");
899 ("list_devices", (RStringList "devices", []), 7, [],
900 [InitEmpty, Always, TestOutputListOfDevices (
901 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
902 "list the block devices",
904 List all the block devices.
906 The full block device names are returned, eg. C</dev/sda>");
908 ("list_partitions", (RStringList "partitions", []), 8, [],
909 [InitBasicFS, Always, TestOutputListOfDevices (
910 [["list_partitions"]], ["/dev/sda1"]);
911 InitEmpty, Always, TestOutputListOfDevices (
912 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
913 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
914 "list the partitions",
916 List all the partitions detected on all block devices.
918 The full partition device names are returned, eg. C</dev/sda1>
920 This does not return logical volumes. For that you will need to
921 call C<guestfs_lvs>.");
923 ("pvs", (RStringList "physvols", []), 9, [],
924 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
925 [["pvs"]], ["/dev/sda1"]);
926 InitEmpty, Always, TestOutputListOfDevices (
927 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
928 ["pvcreate"; "/dev/sda1"];
929 ["pvcreate"; "/dev/sda2"];
930 ["pvcreate"; "/dev/sda3"];
931 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
932 "list the LVM physical volumes (PVs)",
934 List all the physical volumes detected. This is the equivalent
935 of the L<pvs(8)> command.
937 This returns a list of just the device names that contain
938 PVs (eg. C</dev/sda2>).
940 See also C<guestfs_pvs_full>.");
942 ("vgs", (RStringList "volgroups", []), 10, [],
943 [InitBasicFSonLVM, Always, TestOutputList (
945 InitEmpty, Always, TestOutputList (
946 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
947 ["pvcreate"; "/dev/sda1"];
948 ["pvcreate"; "/dev/sda2"];
949 ["pvcreate"; "/dev/sda3"];
950 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
951 ["vgcreate"; "VG2"; "/dev/sda3"];
952 ["vgs"]], ["VG1"; "VG2"])],
953 "list the LVM volume groups (VGs)",
955 List all the volumes groups detected. This is the equivalent
956 of the L<vgs(8)> command.
958 This returns a list of just the volume group names that were
959 detected (eg. C<VolGroup00>).
961 See also C<guestfs_vgs_full>.");
963 ("lvs", (RStringList "logvols", []), 11, [],
964 [InitBasicFSonLVM, Always, TestOutputList (
965 [["lvs"]], ["/dev/VG/LV"]);
966 InitEmpty, Always, TestOutputList (
967 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
968 ["pvcreate"; "/dev/sda1"];
969 ["pvcreate"; "/dev/sda2"];
970 ["pvcreate"; "/dev/sda3"];
971 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
972 ["vgcreate"; "VG2"; "/dev/sda3"];
973 ["lvcreate"; "LV1"; "VG1"; "50"];
974 ["lvcreate"; "LV2"; "VG1"; "50"];
975 ["lvcreate"; "LV3"; "VG2"; "50"];
976 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
977 "list the LVM logical volumes (LVs)",
979 List all the logical volumes detected. This is the equivalent
980 of the L<lvs(8)> command.
982 This returns a list of the logical volume device names
983 (eg. C</dev/VolGroup00/LogVol00>).
985 See also C<guestfs_lvs_full>.");
987 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
988 [], (* XXX how to test? *)
989 "list the LVM physical volumes (PVs)",
991 List all the physical volumes detected. This is the equivalent
992 of the L<pvs(8)> command. The \"full\" version includes all fields.");
994 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
995 [], (* XXX how to test? *)
996 "list the LVM volume groups (VGs)",
998 List all the volumes groups detected. This is the equivalent
999 of the L<vgs(8)> command. The \"full\" version includes all fields.");
1001 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1002 [], (* XXX how to test? *)
1003 "list the LVM logical volumes (LVs)",
1005 List all the logical volumes detected. This is the equivalent
1006 of the L<lvs(8)> command. The \"full\" version includes all fields.");
1008 ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1009 [InitSquashFS, Always, TestOutputList (
1010 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1011 InitSquashFS, Always, TestOutputList (
1012 [["read_lines"; "/empty"]], [])],
1013 "read file as lines",
1015 Return the contents of the file named C<path>.
1017 The file contents are returned as a list of lines. Trailing
1018 C<LF> and C<CRLF> character sequences are I<not> returned.
1020 Note that this function cannot correctly handle binary files
1021 (specifically, files containing C<\\0> character which is treated
1022 as end of line). For those you need to use the C<guestfs_read_file>
1023 function which has a more complex interface.");
1025 ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1026 [], (* XXX Augeas code needs tests. *)
1027 "create a new Augeas handle",
1029 Create a new Augeas handle for editing configuration files.
1030 If there was any previous Augeas handle associated with this
1031 guestfs session, then it is closed.
1033 You must call this before using any other C<guestfs_aug_*>
1036 C<root> is the filesystem root. C<root> must not be NULL,
1039 The flags are the same as the flags defined in
1040 E<lt>augeas.hE<gt>, the logical I<or> of the following
1045 =item C<AUG_SAVE_BACKUP> = 1
1047 Keep the original file with a C<.augsave> extension.
1049 =item C<AUG_SAVE_NEWFILE> = 2
1051 Save changes into a file with extension C<.augnew>, and
1052 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1054 =item C<AUG_TYPE_CHECK> = 4
1056 Typecheck lenses (can be expensive).
1058 =item C<AUG_NO_STDINC> = 8
1060 Do not use standard load path for modules.
1062 =item C<AUG_SAVE_NOOP> = 16
1064 Make save a no-op, just record what would have been changed.
1066 =item C<AUG_NO_LOAD> = 32
1068 Do not load the tree in C<guestfs_aug_init>.
1072 To close the handle, you can call C<guestfs_aug_close>.
1074 To find out more about Augeas, see L<http://augeas.net/>.");
1076 ("aug_close", (RErr, []), 26, [],
1077 [], (* XXX Augeas code needs tests. *)
1078 "close the current Augeas handle",
1080 Close the current Augeas handle and free up any resources
1081 used by it. After calling this, you have to call
1082 C<guestfs_aug_init> again before you can use any other
1083 Augeas functions.");
1085 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1086 [], (* XXX Augeas code needs tests. *)
1087 "define an Augeas variable",
1089 Defines an Augeas variable C<name> whose value is the result
1090 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1093 On success this returns the number of nodes in C<expr>, or
1094 C<0> if C<expr> evaluates to something which is not a nodeset.");
1096 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1097 [], (* XXX Augeas code needs tests. *)
1098 "define an Augeas node",
1100 Defines a variable C<name> whose value is the result of
1103 If C<expr> evaluates to an empty nodeset, a node is created,
1104 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1105 C<name> will be the nodeset containing that single node.
1107 On success this returns a pair containing the
1108 number of nodes in the nodeset, and a boolean flag
1109 if a node was created.");
1111 ("aug_get", (RString "val", [String "augpath"]), 19, [],
1112 [], (* XXX Augeas code needs tests. *)
1113 "look up the value of an Augeas path",
1115 Look up the value associated with C<path>. If C<path>
1116 matches exactly one node, the C<value> is returned.");
1118 ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1119 [], (* XXX Augeas code needs tests. *)
1120 "set Augeas path to value",
1122 Set the value associated with C<path> to C<value>.");
1124 ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1125 [], (* XXX Augeas code needs tests. *)
1126 "insert a sibling Augeas node",
1128 Create a new sibling C<label> for C<path>, inserting it into
1129 the tree before or after C<path> (depending on the boolean
1132 C<path> must match exactly one existing node in the tree, and
1133 C<label> must be a label, ie. not contain C</>, C<*> or end
1134 with a bracketed index C<[N]>.");
1136 ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1137 [], (* XXX Augeas code needs tests. *)
1138 "remove an Augeas path",
1140 Remove C<path> and all of its children.
1142 On success this returns the number of entries which were removed.");
1144 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1145 [], (* XXX Augeas code needs tests. *)
1148 Move the node C<src> to C<dest>. C<src> must match exactly
1149 one node. C<dest> is overwritten if it exists.");
1151 ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1152 [], (* XXX Augeas code needs tests. *)
1153 "return Augeas nodes which match augpath",
1155 Returns a list of paths which match the path expression C<path>.
1156 The returned paths are sufficiently qualified so that they match
1157 exactly one node in the current tree.");
1159 ("aug_save", (RErr, []), 25, [],
1160 [], (* XXX Augeas code needs tests. *)
1161 "write all pending Augeas changes to disk",
1163 This writes all pending changes to disk.
1165 The flags which were passed to C<guestfs_aug_init> affect exactly
1166 how files are saved.");
1168 ("aug_load", (RErr, []), 27, [],
1169 [], (* XXX Augeas code needs tests. *)
1170 "load files into the tree",
1172 Load files into the tree.
1174 See C<aug_load> in the Augeas documentation for the full gory
1177 ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1178 [], (* XXX Augeas code needs tests. *)
1179 "list Augeas nodes under augpath",
1181 This is just a shortcut for listing C<guestfs_aug_match>
1182 C<path/*> and sorting the resulting nodes into alphabetical order.");
1184 ("rm", (RErr, [Pathname "path"]), 29, [],
1185 [InitBasicFS, Always, TestRun
1188 InitBasicFS, Always, TestLastFail
1190 InitBasicFS, Always, TestLastFail
1195 Remove the single file C<path>.");
1197 ("rmdir", (RErr, [Pathname "path"]), 30, [],
1198 [InitBasicFS, Always, TestRun
1201 InitBasicFS, Always, TestLastFail
1202 [["rmdir"; "/new"]];
1203 InitBasicFS, Always, TestLastFail
1205 ["rmdir"; "/new"]]],
1206 "remove a directory",
1208 Remove the single directory C<path>.");
1210 ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1211 [InitBasicFS, Always, TestOutputFalse
1213 ["mkdir"; "/new/foo"];
1214 ["touch"; "/new/foo/bar"];
1216 ["exists"; "/new"]]],
1217 "remove a file or directory recursively",
1219 Remove the file or directory C<path>, recursively removing the
1220 contents if its a directory. This is like the C<rm -rf> shell
1223 ("mkdir", (RErr, [Pathname "path"]), 32, [],
1224 [InitBasicFS, Always, TestOutputTrue
1226 ["is_dir"; "/new"]];
1227 InitBasicFS, Always, TestLastFail
1228 [["mkdir"; "/new/foo/bar"]]],
1229 "create a directory",
1231 Create a directory named C<path>.");
1233 ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1234 [InitBasicFS, Always, TestOutputTrue
1235 [["mkdir_p"; "/new/foo/bar"];
1236 ["is_dir"; "/new/foo/bar"]];
1237 InitBasicFS, Always, TestOutputTrue
1238 [["mkdir_p"; "/new/foo/bar"];
1239 ["is_dir"; "/new/foo"]];
1240 InitBasicFS, Always, TestOutputTrue
1241 [["mkdir_p"; "/new/foo/bar"];
1242 ["is_dir"; "/new"]];
1243 (* Regression tests for RHBZ#503133: *)
1244 InitBasicFS, Always, TestRun
1246 ["mkdir_p"; "/new"]];
1247 InitBasicFS, Always, TestLastFail
1249 ["mkdir_p"; "/new"]]],
1250 "create a directory and parents",
1252 Create a directory named C<path>, creating any parent directories
1253 as necessary. This is like the C<mkdir -p> shell command.");
1255 ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1256 [], (* XXX Need stat command to test *)
1259 Change the mode (permissions) of C<path> to C<mode>. Only
1260 numeric modes are supported.");
1262 ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1263 [], (* XXX Need stat command to test *)
1264 "change file owner and group",
1266 Change the file owner to C<owner> and group to C<group>.
1268 Only numeric uid and gid are supported. If you want to use
1269 names, you will need to locate and parse the password file
1270 yourself (Augeas support makes this relatively easy).");
1272 ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1273 [InitSquashFS, Always, TestOutputTrue (
1274 [["exists"; "/empty"]]);
1275 InitSquashFS, Always, TestOutputTrue (
1276 [["exists"; "/directory"]])],
1277 "test if file or directory exists",
1279 This returns C<true> if and only if there is a file, directory
1280 (or anything) with the given C<path> name.
1282 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1284 ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1285 [InitSquashFS, Always, TestOutputTrue (
1286 [["is_file"; "/known-1"]]);
1287 InitSquashFS, Always, TestOutputFalse (
1288 [["is_file"; "/directory"]])],
1289 "test if file exists",
1291 This returns C<true> if and only if there is a file
1292 with the given C<path> name. Note that it returns false for
1293 other objects like directories.
1295 See also C<guestfs_stat>.");
1297 ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1298 [InitSquashFS, Always, TestOutputFalse (
1299 [["is_dir"; "/known-3"]]);
1300 InitSquashFS, Always, TestOutputTrue (
1301 [["is_dir"; "/directory"]])],
1302 "test if file exists",
1304 This returns C<true> if and only if there is a directory
1305 with the given C<path> name. Note that it returns false for
1306 other objects like files.
1308 See also C<guestfs_stat>.");
1310 ("pvcreate", (RErr, [Device "device"]), 39, [],
1311 [InitEmpty, Always, TestOutputListOfDevices (
1312 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1313 ["pvcreate"; "/dev/sda1"];
1314 ["pvcreate"; "/dev/sda2"];
1315 ["pvcreate"; "/dev/sda3"];
1316 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1317 "create an LVM physical volume",
1319 This creates an LVM physical volume on the named C<device>,
1320 where C<device> should usually be a partition name such
1323 ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
1324 [InitEmpty, Always, TestOutputList (
1325 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1326 ["pvcreate"; "/dev/sda1"];
1327 ["pvcreate"; "/dev/sda2"];
1328 ["pvcreate"; "/dev/sda3"];
1329 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1330 ["vgcreate"; "VG2"; "/dev/sda3"];
1331 ["vgs"]], ["VG1"; "VG2"])],
1332 "create an LVM volume group",
1334 This creates an LVM volume group called C<volgroup>
1335 from the non-empty list of physical volumes C<physvols>.");
1337 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1338 [InitEmpty, Always, TestOutputList (
1339 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1340 ["pvcreate"; "/dev/sda1"];
1341 ["pvcreate"; "/dev/sda2"];
1342 ["pvcreate"; "/dev/sda3"];
1343 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1344 ["vgcreate"; "VG2"; "/dev/sda3"];
1345 ["lvcreate"; "LV1"; "VG1"; "50"];
1346 ["lvcreate"; "LV2"; "VG1"; "50"];
1347 ["lvcreate"; "LV3"; "VG2"; "50"];
1348 ["lvcreate"; "LV4"; "VG2"; "50"];
1349 ["lvcreate"; "LV5"; "VG2"; "50"];
1351 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1352 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1353 "create an LVM volume group",
1355 This creates an LVM volume group called C<logvol>
1356 on the volume group C<volgroup>, with C<size> megabytes.");
1358 ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1359 [InitEmpty, Always, TestOutput (
1360 [["sfdiskM"; "/dev/sda"; ","];
1361 ["mkfs"; "ext2"; "/dev/sda1"];
1362 ["mount"; "/dev/sda1"; "/"];
1363 ["write_file"; "/new"; "new file contents"; "0"];
1364 ["cat"; "/new"]], "new file contents")],
1365 "make a filesystem",
1367 This creates a filesystem on C<device> (usually a partition
1368 or LVM logical volume). The filesystem type is C<fstype>, for
1371 ("sfdisk", (RErr, [Device "device";
1372 Int "cyls"; Int "heads"; Int "sectors";
1373 StringList "lines"]), 43, [DangerWillRobinson],
1375 "create partitions on a block device",
1377 This is a direct interface to the L<sfdisk(8)> program for creating
1378 partitions on block devices.
1380 C<device> should be a block device, for example C</dev/sda>.
1382 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1383 and sectors on the device, which are passed directly to sfdisk as
1384 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1385 of these, then the corresponding parameter is omitted. Usually for
1386 'large' disks, you can just pass C<0> for these, but for small
1387 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1388 out the right geometry and you will need to tell it.
1390 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1391 information refer to the L<sfdisk(8)> manpage.
1393 To create a single partition occupying the whole disk, you would
1394 pass C<lines> as a single element list, when the single element being
1395 the string C<,> (comma).
1397 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1399 ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1400 [InitBasicFS, Always, TestOutput (
1401 [["write_file"; "/new"; "new file contents"; "0"];
1402 ["cat"; "/new"]], "new file contents");
1403 InitBasicFS, Always, TestOutput (
1404 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1405 ["cat"; "/new"]], "\nnew file contents\n");
1406 InitBasicFS, Always, TestOutput (
1407 [["write_file"; "/new"; "\n\n"; "0"];
1408 ["cat"; "/new"]], "\n\n");
1409 InitBasicFS, Always, TestOutput (
1410 [["write_file"; "/new"; ""; "0"];
1411 ["cat"; "/new"]], "");
1412 InitBasicFS, Always, TestOutput (
1413 [["write_file"; "/new"; "\n\n\n"; "0"];
1414 ["cat"; "/new"]], "\n\n\n");
1415 InitBasicFS, Always, TestOutput (
1416 [["write_file"; "/new"; "\n"; "0"];
1417 ["cat"; "/new"]], "\n")],
1420 This call creates a file called C<path>. The contents of the
1421 file is the string C<content> (which can contain any 8 bit data),
1422 with length C<size>.
1424 As a special case, if C<size> is C<0>
1425 then the length is calculated using C<strlen> (so in this case
1426 the content cannot contain embedded ASCII NULs).
1428 I<NB.> Owing to a bug, writing content containing ASCII NUL
1429 characters does I<not> work, even if the length is specified.
1430 We hope to resolve this bug in a future version. In the meantime
1431 use C<guestfs_upload>.");
1433 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1434 [InitEmpty, Always, TestOutputListOfDevices (
1435 [["sfdiskM"; "/dev/sda"; ","];
1436 ["mkfs"; "ext2"; "/dev/sda1"];
1437 ["mount"; "/dev/sda1"; "/"];
1438 ["mounts"]], ["/dev/sda1"]);
1439 InitEmpty, Always, TestOutputList (
1440 [["sfdiskM"; "/dev/sda"; ","];
1441 ["mkfs"; "ext2"; "/dev/sda1"];
1442 ["mount"; "/dev/sda1"; "/"];
1445 "unmount a filesystem",
1447 This unmounts the given filesystem. The filesystem may be
1448 specified either by its mountpoint (path) or the device which
1449 contains the filesystem.");
1451 ("mounts", (RStringList "devices", []), 46, [],
1452 [InitBasicFS, Always, TestOutputListOfDevices (
1453 [["mounts"]], ["/dev/sda1"])],
1454 "show mounted filesystems",
1456 This returns the list of currently mounted filesystems. It returns
1457 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1459 Some internal mounts are not shown.
1461 See also: C<guestfs_mountpoints>");
1463 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1464 [InitBasicFS, Always, TestOutputList (
1467 (* check that umount_all can unmount nested mounts correctly: *)
1468 InitEmpty, Always, TestOutputList (
1469 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1470 ["mkfs"; "ext2"; "/dev/sda1"];
1471 ["mkfs"; "ext2"; "/dev/sda2"];
1472 ["mkfs"; "ext2"; "/dev/sda3"];
1473 ["mount"; "/dev/sda1"; "/"];
1475 ["mount"; "/dev/sda2"; "/mp1"];
1476 ["mkdir"; "/mp1/mp2"];
1477 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1478 ["mkdir"; "/mp1/mp2/mp3"];
1481 "unmount all filesystems",
1483 This unmounts all mounted filesystems.
1485 Some internal mounts are not unmounted by this call.");
1487 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1489 "remove all LVM LVs, VGs and PVs",
1491 This command removes all LVM logical volumes, volume groups
1492 and physical volumes.");
1494 ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1495 [InitSquashFS, Always, TestOutput (
1496 [["file"; "/empty"]], "empty");
1497 InitSquashFS, Always, TestOutput (
1498 [["file"; "/known-1"]], "ASCII text");
1499 InitSquashFS, Always, TestLastFail (
1500 [["file"; "/notexists"]])],
1501 "determine file type",
1503 This call uses the standard L<file(1)> command to determine
1504 the type or contents of the file. This also works on devices,
1505 for example to find out whether a partition contains a filesystem.
1507 This call will also transparently look inside various types
1510 The exact command which runs is C<file -zbsL path>. Note in
1511 particular that the filename is not prepended to the output
1512 (the C<-b> option).");
1514 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1515 [InitBasicFS, Always, TestOutput (
1516 [["upload"; "test-command"; "/test-command"];
1517 ["chmod"; "0o755"; "/test-command"];
1518 ["command"; "/test-command 1"]], "Result1");
1519 InitBasicFS, Always, TestOutput (
1520 [["upload"; "test-command"; "/test-command"];
1521 ["chmod"; "0o755"; "/test-command"];
1522 ["command"; "/test-command 2"]], "Result2\n");
1523 InitBasicFS, Always, TestOutput (
1524 [["upload"; "test-command"; "/test-command"];
1525 ["chmod"; "0o755"; "/test-command"];
1526 ["command"; "/test-command 3"]], "\nResult3");
1527 InitBasicFS, Always, TestOutput (
1528 [["upload"; "test-command"; "/test-command"];
1529 ["chmod"; "0o755"; "/test-command"];
1530 ["command"; "/test-command 4"]], "\nResult4\n");
1531 InitBasicFS, Always, TestOutput (
1532 [["upload"; "test-command"; "/test-command"];
1533 ["chmod"; "0o755"; "/test-command"];
1534 ["command"; "/test-command 5"]], "\nResult5\n\n");
1535 InitBasicFS, Always, TestOutput (
1536 [["upload"; "test-command"; "/test-command"];
1537 ["chmod"; "0o755"; "/test-command"];
1538 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1539 InitBasicFS, Always, TestOutput (
1540 [["upload"; "test-command"; "/test-command"];
1541 ["chmod"; "0o755"; "/test-command"];
1542 ["command"; "/test-command 7"]], "");
1543 InitBasicFS, Always, TestOutput (
1544 [["upload"; "test-command"; "/test-command"];
1545 ["chmod"; "0o755"; "/test-command"];
1546 ["command"; "/test-command 8"]], "\n");
1547 InitBasicFS, Always, TestOutput (
1548 [["upload"; "test-command"; "/test-command"];
1549 ["chmod"; "0o755"; "/test-command"];
1550 ["command"; "/test-command 9"]], "\n\n");
1551 InitBasicFS, Always, TestOutput (
1552 [["upload"; "test-command"; "/test-command"];
1553 ["chmod"; "0o755"; "/test-command"];
1554 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1555 InitBasicFS, Always, TestOutput (
1556 [["upload"; "test-command"; "/test-command"];
1557 ["chmod"; "0o755"; "/test-command"];
1558 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1559 InitBasicFS, Always, TestLastFail (
1560 [["upload"; "test-command"; "/test-command"];
1561 ["chmod"; "0o755"; "/test-command"];
1562 ["command"; "/test-command"]])],
1563 "run a command from the guest filesystem",
1565 This call runs a command from the guest filesystem. The
1566 filesystem must be mounted, and must contain a compatible
1567 operating system (ie. something Linux, with the same
1568 or compatible processor architecture).
1570 The single parameter is an argv-style list of arguments.
1571 The first element is the name of the program to run.
1572 Subsequent elements are parameters. The list must be
1573 non-empty (ie. must contain a program name). Note that
1574 the command runs directly, and is I<not> invoked via
1575 the shell (see C<guestfs_sh>).
1577 The return value is anything printed to I<stdout> by
1580 If the command returns a non-zero exit status, then
1581 this function returns an error message. The error message
1582 string is the content of I<stderr> from the command.
1584 The C<$PATH> environment variable will contain at least
1585 C</usr/bin> and C</bin>. If you require a program from
1586 another location, you should provide the full path in the
1589 Shared libraries and data files required by the program
1590 must be available on filesystems which are mounted in the
1591 correct places. It is the caller's responsibility to ensure
1592 all filesystems that are needed are mounted at the right
1595 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1596 [InitBasicFS, Always, TestOutputList (
1597 [["upload"; "test-command"; "/test-command"];
1598 ["chmod"; "0o755"; "/test-command"];
1599 ["command_lines"; "/test-command 1"]], ["Result1"]);
1600 InitBasicFS, Always, TestOutputList (
1601 [["upload"; "test-command"; "/test-command"];
1602 ["chmod"; "0o755"; "/test-command"];
1603 ["command_lines"; "/test-command 2"]], ["Result2"]);
1604 InitBasicFS, Always, TestOutputList (
1605 [["upload"; "test-command"; "/test-command"];
1606 ["chmod"; "0o755"; "/test-command"];
1607 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1608 InitBasicFS, Always, TestOutputList (
1609 [["upload"; "test-command"; "/test-command"];
1610 ["chmod"; "0o755"; "/test-command"];
1611 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1612 InitBasicFS, Always, TestOutputList (
1613 [["upload"; "test-command"; "/test-command"];
1614 ["chmod"; "0o755"; "/test-command"];
1615 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1616 InitBasicFS, Always, TestOutputList (
1617 [["upload"; "test-command"; "/test-command"];
1618 ["chmod"; "0o755"; "/test-command"];
1619 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1620 InitBasicFS, Always, TestOutputList (
1621 [["upload"; "test-command"; "/test-command"];
1622 ["chmod"; "0o755"; "/test-command"];
1623 ["command_lines"; "/test-command 7"]], []);
1624 InitBasicFS, Always, TestOutputList (
1625 [["upload"; "test-command"; "/test-command"];
1626 ["chmod"; "0o755"; "/test-command"];
1627 ["command_lines"; "/test-command 8"]], [""]);
1628 InitBasicFS, Always, TestOutputList (
1629 [["upload"; "test-command"; "/test-command"];
1630 ["chmod"; "0o755"; "/test-command"];
1631 ["command_lines"; "/test-command 9"]], ["";""]);
1632 InitBasicFS, Always, TestOutputList (
1633 [["upload"; "test-command"; "/test-command"];
1634 ["chmod"; "0o755"; "/test-command"];
1635 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1636 InitBasicFS, Always, TestOutputList (
1637 [["upload"; "test-command"; "/test-command"];
1638 ["chmod"; "0o755"; "/test-command"];
1639 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1640 "run a command, returning lines",
1642 This is the same as C<guestfs_command>, but splits the
1643 result into a list of lines.
1645 See also: C<guestfs_sh_lines>");
1647 ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1648 [InitSquashFS, Always, TestOutputStruct (
1649 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1650 "get file information",
1652 Returns file information for the given C<path>.
1654 This is the same as the C<stat(2)> system call.");
1656 ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1657 [InitSquashFS, Always, TestOutputStruct (
1658 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1659 "get file information for a symbolic link",
1661 Returns file information for the given C<path>.
1663 This is the same as C<guestfs_stat> except that if C<path>
1664 is a symbolic link, then the link is stat-ed, not the file it
1667 This is the same as the C<lstat(2)> system call.");
1669 ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1670 [InitSquashFS, Always, TestOutputStruct (
1671 [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
1672 "get file system statistics",
1674 Returns file system statistics for any mounted file system.
1675 C<path> should be a file or directory in the mounted file system
1676 (typically it is the mount point itself, but it doesn't need to be).
1678 This is the same as the C<statvfs(2)> system call.");
1680 ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1682 "get ext2/ext3/ext4 superblock details",
1684 This returns the contents of the ext2, ext3 or ext4 filesystem
1685 superblock on C<device>.
1687 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1688 manpage for more details. The list of fields returned isn't
1689 clearly defined, and depends on both the version of C<tune2fs>
1690 that libguestfs was built against, and the filesystem itself.");
1692 ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1693 [InitEmpty, Always, TestOutputTrue (
1694 [["blockdev_setro"; "/dev/sda"];
1695 ["blockdev_getro"; "/dev/sda"]])],
1696 "set block device to read-only",
1698 Sets the block device named C<device> to read-only.
1700 This uses the L<blockdev(8)> command.");
1702 ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1703 [InitEmpty, Always, TestOutputFalse (
1704 [["blockdev_setrw"; "/dev/sda"];
1705 ["blockdev_getro"; "/dev/sda"]])],
1706 "set block device to read-write",
1708 Sets the block device named C<device> to read-write.
1710 This uses the L<blockdev(8)> command.");
1712 ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1713 [InitEmpty, Always, TestOutputTrue (
1714 [["blockdev_setro"; "/dev/sda"];
1715 ["blockdev_getro"; "/dev/sda"]])],
1716 "is block device set to read-only",
1718 Returns a boolean indicating if the block device is read-only
1719 (true if read-only, false if not).
1721 This uses the L<blockdev(8)> command.");
1723 ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1724 [InitEmpty, Always, TestOutputInt (
1725 [["blockdev_getss"; "/dev/sda"]], 512)],
1726 "get sectorsize of block device",
1728 This returns the size of sectors on a block device.
1729 Usually 512, but can be larger for modern devices.
1731 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1734 This uses the L<blockdev(8)> command.");
1736 ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1737 [InitEmpty, Always, TestOutputInt (
1738 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1739 "get blocksize of block device",
1741 This returns the block size of a device.
1743 (Note this is different from both I<size in blocks> and
1744 I<filesystem block size>).
1746 This uses the L<blockdev(8)> command.");
1748 ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1750 "set blocksize of block device",
1752 This sets the block size of a device.
1754 (Note this is different from both I<size in blocks> and
1755 I<filesystem block size>).
1757 This uses the L<blockdev(8)> command.");
1759 ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1760 [InitEmpty, Always, TestOutputInt (
1761 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1762 "get total size of device in 512-byte sectors",
1764 This returns the size of the device in units of 512-byte sectors
1765 (even if the sectorsize isn't 512 bytes ... weird).
1767 See also C<guestfs_blockdev_getss> for the real sector size of
1768 the device, and C<guestfs_blockdev_getsize64> for the more
1769 useful I<size in bytes>.
1771 This uses the L<blockdev(8)> command.");
1773 ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1774 [InitEmpty, Always, TestOutputInt (
1775 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1776 "get total size of device in bytes",
1778 This returns the size of the device in bytes.
1780 See also C<guestfs_blockdev_getsz>.
1782 This uses the L<blockdev(8)> command.");
1784 ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1785 [InitEmpty, Always, TestRun
1786 [["blockdev_flushbufs"; "/dev/sda"]]],
1787 "flush device buffers",
1789 This tells the kernel to flush internal buffers associated
1792 This uses the L<blockdev(8)> command.");
1794 ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1795 [InitEmpty, Always, TestRun
1796 [["blockdev_rereadpt"; "/dev/sda"]]],
1797 "reread partition table",
1799 Reread the partition table on C<device>.
1801 This uses the L<blockdev(8)> command.");
1803 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1804 [InitBasicFS, Always, TestOutput (
1805 (* Pick a file from cwd which isn't likely to change. *)
1806 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1807 ["checksum"; "md5"; "/COPYING.LIB"]],
1808 Digest.to_hex (Digest.file "COPYING.LIB"))],
1809 "upload a file from the local machine",
1811 Upload local file C<filename> to C<remotefilename> on the
1814 C<filename> can also be a named pipe.
1816 See also C<guestfs_download>.");
1818 ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1819 [InitBasicFS, Always, TestOutput (
1820 (* Pick a file from cwd which isn't likely to change. *)
1821 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1822 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1823 ["upload"; "testdownload.tmp"; "/upload"];
1824 ["checksum"; "md5"; "/upload"]],
1825 Digest.to_hex (Digest.file "COPYING.LIB"))],
1826 "download a file to the local machine",
1828 Download file C<remotefilename> and save it as C<filename>
1829 on the local machine.
1831 C<filename> can also be a named pipe.
1833 See also C<guestfs_upload>, C<guestfs_cat>.");
1835 ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1836 [InitSquashFS, Always, TestOutput (
1837 [["checksum"; "crc"; "/known-3"]], "2891671662");
1838 InitSquashFS, Always, TestLastFail (
1839 [["checksum"; "crc"; "/notexists"]]);
1840 InitSquashFS, Always, TestOutput (
1841 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1842 InitSquashFS, Always, TestOutput (
1843 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1844 InitSquashFS, Always, TestOutput (
1845 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1846 InitSquashFS, Always, TestOutput (
1847 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1848 InitSquashFS, Always, TestOutput (
1849 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1850 InitSquashFS, Always, TestOutput (
1851 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1852 "compute MD5, SHAx or CRC checksum of file",
1854 This call computes the MD5, SHAx or CRC checksum of the
1857 The type of checksum to compute is given by the C<csumtype>
1858 parameter which must have one of the following values:
1864 Compute the cyclic redundancy check (CRC) specified by POSIX
1865 for the C<cksum> command.
1869 Compute the MD5 hash (using the C<md5sum> program).
1873 Compute the SHA1 hash (using the C<sha1sum> program).
1877 Compute the SHA224 hash (using the C<sha224sum> program).
1881 Compute the SHA256 hash (using the C<sha256sum> program).
1885 Compute the SHA384 hash (using the C<sha384sum> program).
1889 Compute the SHA512 hash (using the C<sha512sum> program).
1893 The checksum is returned as a printable string.");
1895 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1896 [InitBasicFS, Always, TestOutput (
1897 [["tar_in"; "../images/helloworld.tar"; "/"];
1898 ["cat"; "/hello"]], "hello\n")],
1899 "unpack tarfile to directory",
1901 This command uploads and unpacks local file C<tarfile> (an
1902 I<uncompressed> tar file) into C<directory>.
1904 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1906 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1908 "pack directory into tarfile",
1910 This command packs the contents of C<directory> and downloads
1911 it to local file C<tarfile>.
1913 To download a compressed tarball, use C<guestfs_tgz_out>.");
1915 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1916 [InitBasicFS, Always, TestOutput (
1917 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1918 ["cat"; "/hello"]], "hello\n")],
1919 "unpack compressed tarball to directory",
1921 This command uploads and unpacks local file C<tarball> (a
1922 I<gzip compressed> tar file) into C<directory>.
1924 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1926 ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1928 "pack directory into compressed tarball",
1930 This command packs the contents of C<directory> and downloads
1931 it to local file C<tarball>.
1933 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1935 ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1936 [InitBasicFS, Always, TestLastFail (
1938 ["mount_ro"; "/dev/sda1"; "/"];
1939 ["touch"; "/new"]]);
1940 InitBasicFS, Always, TestOutput (
1941 [["write_file"; "/new"; "data"; "0"];
1943 ["mount_ro"; "/dev/sda1"; "/"];
1944 ["cat"; "/new"]], "data")],
1945 "mount a guest disk, read-only",
1947 This is the same as the C<guestfs_mount> command, but it
1948 mounts the filesystem with the read-only (I<-o ro>) flag.");
1950 ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1952 "mount a guest disk with mount options",
1954 This is the same as the C<guestfs_mount> command, but it
1955 allows you to set the mount options as for the
1956 L<mount(8)> I<-o> flag.");
1958 ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1960 "mount a guest disk with mount options and vfstype",
1962 This is the same as the C<guestfs_mount> command, but it
1963 allows you to set both the mount options and the vfstype
1964 as for the L<mount(8)> I<-o> and I<-t> flags.");
1966 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1968 "debugging and internals",
1970 The C<guestfs_debug> command exposes some internals of
1971 C<guestfsd> (the guestfs daemon) that runs inside the
1974 There is no comprehensive help for this command. You have
1975 to look at the file C<daemon/debug.c> in the libguestfs source
1976 to find out what you can do.");
1978 ("lvremove", (RErr, [Device "device"]), 77, [],
1979 [InitEmpty, Always, TestOutputList (
1980 [["sfdiskM"; "/dev/sda"; ","];
1981 ["pvcreate"; "/dev/sda1"];
1982 ["vgcreate"; "VG"; "/dev/sda1"];
1983 ["lvcreate"; "LV1"; "VG"; "50"];
1984 ["lvcreate"; "LV2"; "VG"; "50"];
1985 ["lvremove"; "/dev/VG/LV1"];
1986 ["lvs"]], ["/dev/VG/LV2"]);
1987 InitEmpty, Always, TestOutputList (
1988 [["sfdiskM"; "/dev/sda"; ","];
1989 ["pvcreate"; "/dev/sda1"];
1990 ["vgcreate"; "VG"; "/dev/sda1"];
1991 ["lvcreate"; "LV1"; "VG"; "50"];
1992 ["lvcreate"; "LV2"; "VG"; "50"];
1993 ["lvremove"; "/dev/VG"];
1995 InitEmpty, Always, TestOutputList (
1996 [["sfdiskM"; "/dev/sda"; ","];
1997 ["pvcreate"; "/dev/sda1"];
1998 ["vgcreate"; "VG"; "/dev/sda1"];
1999 ["lvcreate"; "LV1"; "VG"; "50"];
2000 ["lvcreate"; "LV2"; "VG"; "50"];
2001 ["lvremove"; "/dev/VG"];
2003 "remove an LVM logical volume",
2005 Remove an LVM logical volume C<device>, where C<device> is
2006 the path to the LV, such as C</dev/VG/LV>.
2008 You can also remove all LVs in a volume group by specifying
2009 the VG name, C</dev/VG>.");
2011 ("vgremove", (RErr, [String "vgname"]), 78, [],
2012 [InitEmpty, Always, TestOutputList (
2013 [["sfdiskM"; "/dev/sda"; ","];
2014 ["pvcreate"; "/dev/sda1"];
2015 ["vgcreate"; "VG"; "/dev/sda1"];
2016 ["lvcreate"; "LV1"; "VG"; "50"];
2017 ["lvcreate"; "LV2"; "VG"; "50"];
2020 InitEmpty, Always, TestOutputList (
2021 [["sfdiskM"; "/dev/sda"; ","];
2022 ["pvcreate"; "/dev/sda1"];
2023 ["vgcreate"; "VG"; "/dev/sda1"];
2024 ["lvcreate"; "LV1"; "VG"; "50"];
2025 ["lvcreate"; "LV2"; "VG"; "50"];
2028 "remove an LVM volume group",
2030 Remove an LVM volume group C<vgname>, (for example C<VG>).
2032 This also forcibly removes all logical volumes in the volume
2035 ("pvremove", (RErr, [Device "device"]), 79, [],
2036 [InitEmpty, Always, TestOutputListOfDevices (
2037 [["sfdiskM"; "/dev/sda"; ","];
2038 ["pvcreate"; "/dev/sda1"];
2039 ["vgcreate"; "VG"; "/dev/sda1"];
2040 ["lvcreate"; "LV1"; "VG"; "50"];
2041 ["lvcreate"; "LV2"; "VG"; "50"];
2043 ["pvremove"; "/dev/sda1"];
2045 InitEmpty, Always, TestOutputListOfDevices (
2046 [["sfdiskM"; "/dev/sda"; ","];
2047 ["pvcreate"; "/dev/sda1"];
2048 ["vgcreate"; "VG"; "/dev/sda1"];
2049 ["lvcreate"; "LV1"; "VG"; "50"];
2050 ["lvcreate"; "LV2"; "VG"; "50"];
2052 ["pvremove"; "/dev/sda1"];
2054 InitEmpty, Always, TestOutputListOfDevices (
2055 [["sfdiskM"; "/dev/sda"; ","];
2056 ["pvcreate"; "/dev/sda1"];
2057 ["vgcreate"; "VG"; "/dev/sda1"];
2058 ["lvcreate"; "LV1"; "VG"; "50"];
2059 ["lvcreate"; "LV2"; "VG"; "50"];
2061 ["pvremove"; "/dev/sda1"];
2063 "remove an LVM physical volume",
2065 This wipes a physical volume C<device> so that LVM will no longer
2068 The implementation uses the C<pvremove> command which refuses to
2069 wipe physical volumes that contain any volume groups, so you have
2070 to remove those first.");
2072 ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2073 [InitBasicFS, Always, TestOutput (
2074 [["set_e2label"; "/dev/sda1"; "testlabel"];
2075 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2076 "set the ext2/3/4 filesystem label",
2078 This sets the ext2/3/4 filesystem label of the filesystem on
2079 C<device> to C<label>. Filesystem labels are limited to
2082 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2083 to return the existing label on a filesystem.");
2085 ("get_e2label", (RString "label", [Device "device"]), 81, [],
2087 "get the ext2/3/4 filesystem label",
2089 This returns the ext2/3/4 filesystem label of the filesystem on
2092 ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2093 (let uuid = uuidgen () in
2094 [InitBasicFS, Always, TestOutput (
2095 [["set_e2uuid"; "/dev/sda1"; uuid];
2096 ["get_e2uuid"; "/dev/sda1"]], uuid);
2097 InitBasicFS, Always, TestOutput (
2098 [["set_e2uuid"; "/dev/sda1"; "clear"];
2099 ["get_e2uuid"; "/dev/sda1"]], "");
2100 (* We can't predict what UUIDs will be, so just check the commands run. *)
2101 InitBasicFS, Always, TestRun (
2102 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2103 InitBasicFS, Always, TestRun (
2104 [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2105 "set the ext2/3/4 filesystem UUID",
2107 This sets the ext2/3/4 filesystem UUID of the filesystem on
2108 C<device> to C<uuid>. The format of the UUID and alternatives
2109 such as C<clear>, C<random> and C<time> are described in the
2110 L<tune2fs(8)> manpage.
2112 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2113 to return the existing UUID of a filesystem.");
2115 ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2117 "get the ext2/3/4 filesystem UUID",
2119 This returns the ext2/3/4 filesystem UUID of the filesystem on
2122 ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2123 [InitBasicFS, Always, TestOutputInt (
2124 [["umount"; "/dev/sda1"];
2125 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2126 InitBasicFS, Always, TestOutputInt (
2127 [["umount"; "/dev/sda1"];
2128 ["zero"; "/dev/sda1"];
2129 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2130 "run the filesystem checker",
2132 This runs the filesystem checker (fsck) on C<device> which
2133 should have filesystem type C<fstype>.
2135 The returned integer is the status. See L<fsck(8)> for the
2136 list of status codes from C<fsck>.
2144 Multiple status codes can be summed together.
2148 A non-zero return code can mean \"success\", for example if
2149 errors have been corrected on the filesystem.
2153 Checking or repairing NTFS volumes is not supported
2158 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2160 ("zero", (RErr, [Device "device"]), 85, [],
2161 [InitBasicFS, Always, TestOutput (
2162 [["umount"; "/dev/sda1"];
2163 ["zero"; "/dev/sda1"];
2164 ["file"; "/dev/sda1"]], "data")],
2165 "write zeroes to the device",
2167 This command writes zeroes over the first few blocks of C<device>.
2169 How many blocks are zeroed isn't specified (but it's I<not> enough
2170 to securely wipe the device). It should be sufficient to remove
2171 any partition tables, filesystem superblocks and so on.
2173 See also: C<guestfs_scrub_device>.");
2175 ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2176 (* Test disabled because grub-install incompatible with virtio-blk driver.
2177 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2179 [InitBasicFS, Disabled, TestOutputTrue (
2180 [["grub_install"; "/"; "/dev/sda1"];
2181 ["is_dir"; "/boot"]])],
2184 This command installs GRUB (the Grand Unified Bootloader) on
2185 C<device>, with the root directory being C<root>.");
2187 ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2188 [InitBasicFS, Always, TestOutput (
2189 [["write_file"; "/old"; "file content"; "0"];
2190 ["cp"; "/old"; "/new"];
2191 ["cat"; "/new"]], "file content");
2192 InitBasicFS, Always, TestOutputTrue (
2193 [["write_file"; "/old"; "file content"; "0"];
2194 ["cp"; "/old"; "/new"];
2195 ["is_file"; "/old"]]);
2196 InitBasicFS, Always, TestOutput (
2197 [["write_file"; "/old"; "file content"; "0"];
2199 ["cp"; "/old"; "/dir/new"];
2200 ["cat"; "/dir/new"]], "file content")],
2203 This copies a file from C<src> to C<dest> where C<dest> is
2204 either a destination filename or destination directory.");
2206 ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2207 [InitBasicFS, Always, TestOutput (
2208 [["mkdir"; "/olddir"];
2209 ["mkdir"; "/newdir"];
2210 ["write_file"; "/olddir/file"; "file content"; "0"];
2211 ["cp_a"; "/olddir"; "/newdir"];
2212 ["cat"; "/newdir/olddir/file"]], "file content")],
2213 "copy a file or directory recursively",
2215 This copies a file or directory from C<src> to C<dest>
2216 recursively using the C<cp -a> command.");
2218 ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2219 [InitBasicFS, Always, TestOutput (
2220 [["write_file"; "/old"; "file content"; "0"];
2221 ["mv"; "/old"; "/new"];
2222 ["cat"; "/new"]], "file content");
2223 InitBasicFS, Always, TestOutputFalse (
2224 [["write_file"; "/old"; "file content"; "0"];
2225 ["mv"; "/old"; "/new"];
2226 ["is_file"; "/old"]])],
2229 This moves a file from C<src> to C<dest> where C<dest> is
2230 either a destination filename or destination directory.");
2232 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2233 [InitEmpty, Always, TestRun (
2234 [["drop_caches"; "3"]])],
2235 "drop kernel page cache, dentries and inodes",
2237 This instructs the guest kernel to drop its page cache,
2238 and/or dentries and inode caches. The parameter C<whattodrop>
2239 tells the kernel what precisely to drop, see
2240 L<http://linux-mm.org/Drop_Caches>
2242 Setting C<whattodrop> to 3 should drop everything.
2244 This automatically calls L<sync(2)> before the operation,
2245 so that the maximum guest memory is freed.");
2247 ("dmesg", (RString "kmsgs", []), 91, [],
2248 [InitEmpty, Always, TestRun (
2250 "return kernel messages",
2252 This returns the kernel messages (C<dmesg> output) from
2253 the guest kernel. This is sometimes useful for extended
2254 debugging of problems.
2256 Another way to get the same information is to enable
2257 verbose messages with C<guestfs_set_verbose> or by setting
2258 the environment variable C<LIBGUESTFS_DEBUG=1> before
2259 running the program.");
2261 ("ping_daemon", (RErr, []), 92, [],
2262 [InitEmpty, Always, TestRun (
2263 [["ping_daemon"]])],
2264 "ping the guest daemon",
2266 This is a test probe into the guestfs daemon running inside
2267 the qemu subprocess. Calling this function checks that the
2268 daemon responds to the ping message, without affecting the daemon
2269 or attached block device(s) in any other way.");
2271 ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2272 [InitBasicFS, Always, TestOutputTrue (
2273 [["write_file"; "/file1"; "contents of a file"; "0"];
2274 ["cp"; "/file1"; "/file2"];
2275 ["equal"; "/file1"; "/file2"]]);
2276 InitBasicFS, Always, TestOutputFalse (
2277 [["write_file"; "/file1"; "contents of a file"; "0"];
2278 ["write_file"; "/file2"; "contents of another file"; "0"];
2279 ["equal"; "/file1"; "/file2"]]);
2280 InitBasicFS, Always, TestLastFail (
2281 [["equal"; "/file1"; "/file2"]])],
2282 "test if two files have equal contents",
2284 This compares the two files C<file1> and C<file2> and returns
2285 true if their content is exactly equal, or false otherwise.
2287 The external L<cmp(1)> program is used for the comparison.");
2289 ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2290 [InitSquashFS, Always, TestOutputList (
2291 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2292 InitSquashFS, Always, TestOutputList (
2293 [["strings"; "/empty"]], [])],
2294 "print the printable strings in a file",
2296 This runs the L<strings(1)> command on a file and returns
2297 the list of printable strings found.");
2299 ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2300 [InitSquashFS, Always, TestOutputList (
2301 [["strings_e"; "b"; "/known-5"]], []);
2302 InitBasicFS, Disabled, TestOutputList (
2303 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2304 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2305 "print the printable strings in a file",
2307 This is like the C<guestfs_strings> command, but allows you to
2308 specify the encoding.
2310 See the L<strings(1)> manpage for the full list of encodings.
2312 Commonly useful encodings are C<l> (lower case L) which will
2313 show strings inside Windows/x86 files.
2315 The returned strings are transcoded to UTF-8.");
2317 ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2318 [InitSquashFS, Always, TestOutput (
2319 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2320 (* Test for RHBZ#501888c2 regression which caused large hexdump
2321 * commands to segfault.
2323 InitSquashFS, Always, TestRun (
2324 [["hexdump"; "/100krandom"]])],
2325 "dump a file in hexadecimal",
2327 This runs C<hexdump -C> on the given C<path>. The result is
2328 the human-readable, canonical hex dump of the file.");
2330 ("zerofree", (RErr, [Device "device"]), 97, [],
2331 [InitNone, Always, TestOutput (
2332 [["sfdiskM"; "/dev/sda"; ","];
2333 ["mkfs"; "ext3"; "/dev/sda1"];
2334 ["mount"; "/dev/sda1"; "/"];
2335 ["write_file"; "/new"; "test file"; "0"];
2336 ["umount"; "/dev/sda1"];
2337 ["zerofree"; "/dev/sda1"];
2338 ["mount"; "/dev/sda1"; "/"];
2339 ["cat"; "/new"]], "test file")],
2340 "zero unused inodes and disk blocks on ext2/3 filesystem",
2342 This runs the I<zerofree> program on C<device>. This program
2343 claims to zero unused inodes and disk blocks on an ext2/3
2344 filesystem, thus making it possible to compress the filesystem
2347 You should B<not> run this program if the filesystem is
2350 It is possible that using this program can damage the filesystem
2351 or data on the filesystem.");
2353 ("pvresize", (RErr, [Device "device"]), 98, [],
2355 "resize an LVM physical volume",
2357 This resizes (expands or shrinks) an existing LVM physical
2358 volume to match the new size of the underlying device.");
2360 ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2361 Int "cyls"; Int "heads"; Int "sectors";
2362 String "line"]), 99, [DangerWillRobinson],
2364 "modify a single partition on a block device",
2366 This runs L<sfdisk(8)> option to modify just the single
2367 partition C<n> (note: C<n> counts from 1).
2369 For other parameters, see C<guestfs_sfdisk>. You should usually
2370 pass C<0> for the cyls/heads/sectors parameters.");
2372 ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2374 "display the partition table",
2376 This displays the partition table on C<device>, in the
2377 human-readable output of the L<sfdisk(8)> command. It is
2378 not intended to be parsed.");
2380 ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2382 "display the kernel geometry",
2384 This displays the kernel's idea of the geometry of C<device>.
2386 The result is in human-readable format, and not designed to
2389 ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2391 "display the disk geometry from the partition table",
2393 This displays the disk geometry of C<device> read from the
2394 partition table. Especially in the case where the underlying
2395 block device has been resized, this can be different from the
2396 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2398 The result is in human-readable format, and not designed to
2401 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2403 "activate or deactivate all volume groups",
2405 This command activates or (if C<activate> is false) deactivates
2406 all logical volumes in all volume groups.
2407 If activated, then they are made known to the
2408 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2409 then those devices disappear.
2411 This command is the same as running C<vgchange -a y|n>");
2413 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2415 "activate or deactivate some volume groups",
2417 This command activates or (if C<activate> is false) deactivates
2418 all logical volumes in the listed volume groups C<volgroups>.
2419 If activated, then they are made known to the
2420 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2421 then those devices disappear.
2423 This command is the same as running C<vgchange -a y|n volgroups...>
2425 Note that if C<volgroups> is an empty list then B<all> volume groups
2426 are activated or deactivated.");
2428 ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2429 [InitNone, Always, TestOutput (
2430 [["sfdiskM"; "/dev/sda"; ","];
2431 ["pvcreate"; "/dev/sda1"];
2432 ["vgcreate"; "VG"; "/dev/sda1"];
2433 ["lvcreate"; "LV"; "VG"; "10"];
2434 ["mkfs"; "ext2"; "/dev/VG/LV"];
2435 ["mount"; "/dev/VG/LV"; "/"];
2436 ["write_file"; "/new"; "test content"; "0"];
2438 ["lvresize"; "/dev/VG/LV"; "20"];
2439 ["e2fsck_f"; "/dev/VG/LV"];
2440 ["resize2fs"; "/dev/VG/LV"];
2441 ["mount"; "/dev/VG/LV"; "/"];
2442 ["cat"; "/new"]], "test content")],
2443 "resize an LVM logical volume",
2445 This resizes (expands or shrinks) an existing LVM logical
2446 volume to C<mbytes>. When reducing, data in the reduced part
2449 ("resize2fs", (RErr, [Device "device"]), 106, [],
2450 [], (* lvresize tests this *)
2451 "resize an ext2/ext3 filesystem",
2453 This resizes an ext2 or ext3 filesystem to match the size of
2454 the underlying device.
2456 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2457 on the C<device> before calling this command. For unknown reasons
2458 C<resize2fs> sometimes gives an error about this and sometimes not.
2459 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2460 calling this function.");
2462 ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2463 [InitBasicFS, Always, TestOutputList (
2464 [["find"; "/"]], ["lost+found"]);
2465 InitBasicFS, Always, TestOutputList (
2469 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2470 InitBasicFS, Always, TestOutputList (
2471 [["mkdir_p"; "/a/b/c"];
2472 ["touch"; "/a/b/c/d"];
2473 ["find"; "/a/b/"]], ["c"; "c/d"])],
2474 "find all files and directories",
2476 This command lists out all files and directories, recursively,
2477 starting at C<directory>. It is essentially equivalent to
2478 running the shell command C<find directory -print> but some
2479 post-processing happens on the output, described below.
2481 This returns a list of strings I<without any prefix>. Thus
2482 if the directory structure was:
2488 then the returned list from C<guestfs_find> C</tmp> would be
2496 If C<directory> is not a directory, then this command returns
2499 The returned list is sorted.");
2501 ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2502 [], (* lvresize tests this *)
2503 "check an ext2/ext3 filesystem",
2505 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2506 filesystem checker on C<device>, noninteractively (C<-p>),
2507 even if the filesystem appears to be clean (C<-f>).
2509 This command is only needed because of C<guestfs_resize2fs>
2510 (q.v.). Normally you should use C<guestfs_fsck>.");
2512 ("sleep", (RErr, [Int "secs"]), 109, [],
2513 [InitNone, Always, TestRun (
2515 "sleep for some seconds",
2517 Sleep for C<secs> seconds.");
2519 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2520 [InitNone, Always, TestOutputInt (
2521 [["sfdiskM"; "/dev/sda"; ","];
2522 ["mkfs"; "ntfs"; "/dev/sda1"];
2523 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2524 InitNone, Always, TestOutputInt (
2525 [["sfdiskM"; "/dev/sda"; ","];
2526 ["mkfs"; "ext2"; "/dev/sda1"];
2527 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2528 "probe NTFS volume",
2530 This command runs the L<ntfs-3g.probe(8)> command which probes
2531 an NTFS C<device> for mountability. (Not all NTFS volumes can
2532 be mounted read-write, and some cannot be mounted at all).
2534 C<rw> is a boolean flag. Set it to true if you want to test
2535 if the volume can be mounted read-write. Set it to false if
2536 you want to test if the volume can be mounted read-only.
2538 The return value is an integer which C<0> if the operation
2539 would succeed, or some non-zero value documented in the
2540 L<ntfs-3g.probe(8)> manual page.");
2542 ("sh", (RString "output", [String "command"]), 111, [],
2543 [], (* XXX needs tests *)
2544 "run a command via the shell",
2546 This call runs a command from the guest filesystem via the
2549 This is like C<guestfs_command>, but passes the command to:
2551 /bin/sh -c \"command\"
2553 Depending on the guest's shell, this usually results in
2554 wildcards being expanded, shell expressions being interpolated
2557 All the provisos about C<guestfs_command> apply to this call.");
2559 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2560 [], (* XXX needs tests *)
2561 "run a command via the shell returning lines",
2563 This is the same as C<guestfs_sh>, but splits the result
2564 into a list of lines.
2566 See also: C<guestfs_command_lines>");
2568 ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2569 (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2570 * code in stubs.c, since all valid glob patterns must start with "/".
2571 * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2573 [InitBasicFS, Always, TestOutputList (
2574 [["mkdir_p"; "/a/b/c"];
2575 ["touch"; "/a/b/c/d"];
2576 ["touch"; "/a/b/c/e"];
2577 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2578 InitBasicFS, Always, TestOutputList (
2579 [["mkdir_p"; "/a/b/c"];
2580 ["touch"; "/a/b/c/d"];
2581 ["touch"; "/a/b/c/e"];
2582 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2583 InitBasicFS, Always, TestOutputList (
2584 [["mkdir_p"; "/a/b/c"];
2585 ["touch"; "/a/b/c/d"];
2586 ["touch"; "/a/b/c/e"];
2587 ["glob_expand"; "/a/*/x/*"]], [])],
2588 "expand a wildcard path",
2590 This command searches for all the pathnames matching
2591 C<pattern> according to the wildcard expansion rules
2594 If no paths match, then this returns an empty list
2595 (note: not an error).
2597 It is just a wrapper around the C L<glob(3)> function
2598 with flags C<GLOB_MARK|GLOB_BRACE>.
2599 See that manual page for more details.");
2601 ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2602 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2603 [["scrub_device"; "/dev/sdc"]])],
2604 "scrub (securely wipe) a device",
2606 This command writes patterns over C<device> to make data retrieval
2609 It is an interface to the L<scrub(1)> program. See that
2610 manual page for more details.");
2612 ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2613 [InitBasicFS, Always, TestRun (
2614 [["write_file"; "/file"; "content"; "0"];
2615 ["scrub_file"; "/file"]])],
2616 "scrub (securely wipe) a file",
2618 This command writes patterns over a file to make data retrieval
2621 The file is I<removed> after scrubbing.
2623 It is an interface to the L<scrub(1)> program. See that
2624 manual page for more details.");
2626 ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2627 [], (* XXX needs testing *)
2628 "scrub (securely wipe) free space",
2630 This command creates the directory C<dir> and then fills it
2631 with files until the filesystem is full, and scrubs the files
2632 as for C<guestfs_scrub_file>, and deletes them.
2633 The intention is to scrub any free space on the partition
2636 It is an interface to the L<scrub(1)> program. See that
2637 manual page for more details.");
2639 ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2640 [InitBasicFS, Always, TestRun (
2642 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2643 "create a temporary directory",
2645 This command creates a temporary directory. The
2646 C<template> parameter should be a full pathname for the
2647 temporary directory name with the final six characters being
2650 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2651 the second one being suitable for Windows filesystems.
2653 The name of the temporary directory that was created
2656 The temporary directory is created with mode 0700
2657 and is owned by root.
2659 The caller is responsible for deleting the temporary
2660 directory and its contents after use.
2662 See also: L<mkdtemp(3)>");
2664 ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2665 [InitSquashFS, Always, TestOutputInt (
2666 [["wc_l"; "/10klines"]], 10000)],
2667 "count lines in a file",
2669 This command counts the lines in a file, using the
2670 C<wc -l> external command.");
2672 ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2673 [InitSquashFS, Always, TestOutputInt (
2674 [["wc_w"; "/10klines"]], 10000)],
2675 "count words in a file",
2677 This command counts the words in a file, using the
2678 C<wc -w> external command.");
2680 ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2681 [InitSquashFS, Always, TestOutputInt (
2682 [["wc_c"; "/100kallspaces"]], 102400)],
2683 "count characters in a file",
2685 This command counts the characters in a file, using the
2686 C<wc -c> external command.");
2688 ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2689 [InitSquashFS, Always, TestOutputList (
2690 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2691 "return first 10 lines of a file",
2693 This command returns up to the first 10 lines of a file as
2694 a list of strings.");
2696 ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2697 [InitSquashFS, Always, TestOutputList (
2698 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2699 InitSquashFS, Always, TestOutputList (
2700 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2701 InitSquashFS, Always, TestOutputList (
2702 [["head_n"; "0"; "/10klines"]], [])],
2703 "return first N lines of a file",
2705 If the parameter C<nrlines> is a positive number, this returns the first
2706 C<nrlines> lines of the file C<path>.
2708 If the parameter C<nrlines> is a negative number, this returns lines
2709 from the file C<path>, excluding the last C<nrlines> lines.
2711 If the parameter C<nrlines> is zero, this returns an empty list.");
2713 ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2714 [InitSquashFS, Always, TestOutputList (
2715 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2716 "return last 10 lines of a file",
2718 This command returns up to the last 10 lines of a file as
2719 a list of strings.");
2721 ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2722 [InitSquashFS, Always, TestOutputList (
2723 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2724 InitSquashFS, Always, TestOutputList (
2725 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2726 InitSquashFS, Always, TestOutputList (
2727 [["tail_n"; "0"; "/10klines"]], [])],
2728 "return last N lines of a file",
2730 If the parameter C<nrlines> is a positive number, this returns the last
2731 C<nrlines> lines of the file C<path>.
2733 If the parameter C<nrlines> is a negative number, this returns lines
2734 from the file C<path>, starting with the C<-nrlines>th line.
2736 If the parameter C<nrlines> is zero, this returns an empty list.");
2738 ("df", (RString "output", []), 125, [],
2739 [], (* XXX Tricky to test because it depends on the exact format
2740 * of the 'df' command and other imponderables.
2742 "report file system disk space usage",
2744 This command runs the C<df> command to report disk space used.
2746 This command is mostly useful for interactive sessions. It
2747 is I<not> intended that you try to parse the output string.
2748 Use C<statvfs> from programs.");
2750 ("df_h", (RString "output", []), 126, [],
2751 [], (* XXX Tricky to test because it depends on the exact format
2752 * of the 'df' command and other imponderables.
2754 "report file system disk space usage (human readable)",
2756 This command runs the C<df -h> command to report disk space used
2757 in human-readable format.
2759 This command is mostly useful for interactive sessions. It
2760 is I<not> intended that you try to parse the output string.
2761 Use C<statvfs> from programs.");
2763 ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2764 [InitSquashFS, Always, TestOutputInt (
2765 [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))],
2766 "estimate file space usage",
2768 This command runs the C<du -s> command to estimate file space
2771 C<path> can be a file or a directory. If C<path> is a directory
2772 then the estimate includes the contents of the directory and all
2773 subdirectories (recursively).
2775 The result is the estimated size in I<kilobytes>
2776 (ie. units of 1024 bytes).");
2778 ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2779 [InitSquashFS, Always, TestOutputList (
2780 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2781 "list files in an initrd",
2783 This command lists out files contained in an initrd.
2785 The files are listed without any initial C</> character. The
2786 files are listed in the order they appear (not necessarily
2787 alphabetical). Directory names are listed as separate items.
2789 Old Linux kernels (2.4 and earlier) used a compressed ext2
2790 filesystem as initrd. We I<only> support the newer initramfs
2791 format (compressed cpio files).");
2793 ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2795 "mount a file using the loop device",
2797 This command lets you mount C<file> (a filesystem image
2798 in a file) on a mount point. It is entirely equivalent to
2799 the command C<mount -o loop file mountpoint>.");
2801 ("mkswap", (RErr, [Device "device"]), 130, [],
2802 [InitEmpty, Always, TestRun (
2803 [["sfdiskM"; "/dev/sda"; ","];
2804 ["mkswap"; "/dev/sda1"]])],
2805 "create a swap partition",
2807 Create a swap partition on C<device>.");
2809 ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2810 [InitEmpty, Always, TestRun (
2811 [["sfdiskM"; "/dev/sda"; ","];
2812 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2813 "create a swap partition with a label",
2815 Create a swap partition on C<device> with label C<label>.
2817 Note that you cannot attach a swap label to a block device
2818 (eg. C</dev/sda>), just to a partition. This appears to be
2819 a limitation of the kernel or swap tools.");
2821 ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2822 (let uuid = uuidgen () in
2823 [InitEmpty, Always, TestRun (
2824 [["sfdiskM"; "/dev/sda"; ","];
2825 ["mkswap_U"; uuid; "/dev/sda1"]])]),
2826 "create a swap partition with an explicit UUID",
2828 Create a swap partition on C<device> with UUID C<uuid>.");
2830 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2831 [InitBasicFS, Always, TestOutputStruct (
2832 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2833 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2834 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2835 InitBasicFS, Always, TestOutputStruct (
2836 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2837 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2838 "make block, character or FIFO devices",
2840 This call creates block or character special devices, or
2841 named pipes (FIFOs).
2843 The C<mode> parameter should be the mode, using the standard
2844 constants. C<devmajor> and C<devminor> are the
2845 device major and minor numbers, only used when creating block
2846 and character special devices.");
2848 ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2849 [InitBasicFS, Always, TestOutputStruct (
2850 [["mkfifo"; "0o777"; "/node"];
2851 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2852 "make FIFO (named pipe)",
2854 This call creates a FIFO (named pipe) called C<path> with
2855 mode C<mode>. It is just a convenient wrapper around
2856 C<guestfs_mknod>.");
2858 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2859 [InitBasicFS, Always, TestOutputStruct (
2860 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2861 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2862 "make block device node",
2864 This call creates a block device node called C<path> with
2865 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2866 It is just a convenient wrapper around C<guestfs_mknod>.");
2868 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2869 [InitBasicFS, Always, TestOutputStruct (
2870 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2871 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2872 "make char device node",
2874 This call creates a char device node called C<path> with
2875 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2876 It is just a convenient wrapper around C<guestfs_mknod>.");
2878 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2879 [], (* XXX umask is one of those stateful things that we should
2880 * reset between each test.
2882 "set file mode creation mask (umask)",
2884 This function sets the mask used for creating new files and
2885 device nodes to C<mask & 0777>.
2887 Typical umask values would be C<022> which creates new files
2888 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2889 C<002> which creates new files with permissions like
2890 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2892 The default umask is C<022>. This is important because it
2893 means that directories and device nodes will be created with
2894 C<0644> or C<0755> mode even if you specify C<0777>.
2896 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2898 This call returns the previous umask.");
2900 ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2902 "read directories entries",
2904 This returns the list of directory entries in directory C<dir>.
2906 All entries in the directory are returned, including C<.> and
2907 C<..>. The entries are I<not> sorted, but returned in the same
2908 order as the underlying filesystem.
2910 Also this call returns basic file type information about each
2911 file. The C<ftyp> field will contain one of the following characters:
2949 The L<readdir(3)> returned a C<d_type> field with an
2954 This function is primarily intended for use by programs. To
2955 get a simple list of names, use C<guestfs_ls>. To get a printable
2956 directory for human consumption, use C<guestfs_ll>.");
2958 ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2960 "create partitions on a block device",
2962 This is a simplified interface to the C<guestfs_sfdisk>
2963 command, where partition sizes are specified in megabytes
2964 only (rounded to the nearest cylinder) and you don't need
2965 to specify the cyls, heads and sectors parameters which
2966 were rarely if ever used anyway.
2968 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2970 ("zfile", (RString "description", [String "method"; Pathname "path"]), 140, [DeprecatedBy "file"],
2972 "determine file type inside a compressed file",
2974 This command runs C<file> after first decompressing C<path>
2977 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2979 Since 1.0.63, use C<guestfs_file> instead which can now
2980 process compressed files.");
2982 ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
2984 "list extended attributes of a file or directory",
2986 This call lists the extended attributes of the file or directory
2989 At the system call level, this is a combination of the
2990 L<listxattr(2)> and L<getxattr(2)> calls.
2992 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2994 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
2996 "list extended attributes of a file or directory",
2998 This is the same as C<guestfs_getxattrs>, but if C<path>
2999 is a symbolic link, then it returns the extended attributes
3000 of the link itself.");
3002 ("setxattr", (RErr, [String "xattr";
3003 String "val"; Int "vallen"; (* will be BufferIn *)
3004 Pathname "path"]), 143, [],
3006 "set extended attribute of a file or directory",
3008 This call sets the extended attribute named C<xattr>
3009 of the file C<path> to the value C<val> (of length C<vallen>).
3010 The value is arbitrary 8 bit data.
3012 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3014 ("lsetxattr", (RErr, [String "xattr";
3015 String "val"; Int "vallen"; (* will be BufferIn *)
3016 Pathname "path"]), 144, [],
3018 "set extended attribute of a file or directory",
3020 This is the same as C<guestfs_setxattr>, but if C<path>
3021 is a symbolic link, then it sets an extended attribute
3022 of the link itself.");
3024 ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3026 "remove extended attribute of a file or directory",
3028 This call removes the extended attribute named C<xattr>
3029 of the file C<path>.
3031 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3033 ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3035 "remove extended attribute of a file or directory",
3037 This is the same as C<guestfs_removexattr>, but if C<path>
3038 is a symbolic link, then it removes an extended attribute
3039 of the link itself.");
3041 ("mountpoints", (RHashtable "mps", []), 147, [],
3045 This call is similar to C<guestfs_mounts>. That call returns
3046 a list of devices. This one returns a hash table (map) of
3047 device name to directory where the device is mounted.");
3049 ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3050 (* This is a special case: while you would expect a parameter
3051 * of type "Pathname", that doesn't work, because it implies
3052 * NEED_ROOT in the generated calling code in stubs.c, and
3053 * this function cannot use NEED_ROOT.
3056 "create a mountpoint",
3058 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3059 specialized calls that can be used to create extra mountpoints
3060 before mounting the first filesystem.
3062 These calls are I<only> necessary in some very limited circumstances,
3063 mainly the case where you want to mount a mix of unrelated and/or
3064 read-only filesystems together.
3066 For example, live CDs often contain a \"Russian doll\" nest of
3067 filesystems, an ISO outer layer, with a squashfs image inside, with
3068 an ext2/3 image inside that. You can unpack this as follows
3071 add-ro Fedora-11-i686-Live.iso
3074 mkmountpoint /squash
3077 mount-loop /cd/LiveOS/squashfs.img /squash
3078 mount-loop /squash/LiveOS/ext3fs.img /ext3
3080 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3082 ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3084 "remove a mountpoint",
3086 This calls removes a mountpoint that was previously created
3087 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3088 for full details.");
3090 ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3091 [InitSquashFS, Always, TestOutputBuffer (
3092 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3095 This calls returns the contents of the file C<path> as a
3098 Unlike C<guestfs_cat>, this function can correctly
3099 handle files that contain embedded ASCII NUL characters.
3100 However unlike C<guestfs_download>, this function is limited
3101 in the total size of file that can be handled.");
3103 ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3104 [InitSquashFS, Always, TestOutputList (
3105 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3106 InitSquashFS, Always, TestOutputList (
3107 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3108 "return lines matching a pattern",
3110 This calls the external C<grep> program and returns the
3113 ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3114 [InitSquashFS, Always, TestOutputList (
3115 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3116 "return lines matching a pattern",
3118 This calls the external C<egrep> program and returns the
3121 ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3122 [InitSquashFS, Always, TestOutputList (
3123 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3124 "return lines matching a pattern",
3126 This calls the external C<fgrep> program and returns the
3129 ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3130 [InitSquashFS, Always, TestOutputList (
3131 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3132 "return lines matching a pattern",
3134 This calls the external C<grep -i> program and returns the
3137 ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3138 [InitSquashFS, Always, TestOutputList (
3139 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3140 "return lines matching a pattern",
3142 This calls the external C<egrep -i> program and returns the
3145 ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3146 [InitSquashFS, Always, TestOutputList (
3147 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3148 "return lines matching a pattern",
3150 This calls the external C<fgrep -i> program and returns the
3153 ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3154 [InitSquashFS, Always, TestOutputList (
3155 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3156 "return lines matching a pattern",
3158 This calls the external C<zgrep> program and returns the
3161 ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3162 [InitSquashFS, Always, TestOutputList (
3163 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3164 "return lines matching a pattern",
3166 This calls the external C<zegrep> program and returns the
3169 ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3170 [InitSquashFS, Always, TestOutputList (
3171 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3172 "return lines matching a pattern",
3174 This calls the external C<zfgrep> program and returns the
3177 ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3178 [InitSquashFS, Always, TestOutputList (
3179 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3180 "return lines matching a pattern",
3182 This calls the external C<zgrep -i> program and returns the
3185 ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3186 [InitSquashFS, Always, TestOutputList (
3187 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3188 "return lines matching a pattern",
3190 This calls the external C<zegrep -i> program and returns the
3193 ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3194 [InitSquashFS, Always, TestOutputList (
3195 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3196 "return lines matching a pattern",
3198 This calls the external C<zfgrep -i> program and returns the
3201 ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3202 [InitSquashFS, Always, TestOutput (
3203 [["realpath"; "/../directory"]], "/directory")],
3204 "canonicalized absolute pathname",
3206 Return the canonicalized absolute pathname of C<path>. The
3207 returned path has no C<.>, C<..> or symbolic link path elements.");
3209 ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3210 [InitBasicFS, Always, TestOutputStruct (
3213 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3214 "create a hard link",
3216 This command creates a hard link using the C<ln> command.");
3218 ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3219 [InitBasicFS, Always, TestOutputStruct (
3222 ["ln_f"; "/a"; "/b"];
3223 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3224 "create a hard link",
3226 This command creates a hard link using the C<ln -f> command.
3227 The C<-f> option removes the link (C<linkname>) if it exists already.");
3229 ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3230 [InitBasicFS, Always, TestOutputStruct (
3232 ["ln_s"; "a"; "/b"];
3233 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3234 "create a symbolic link",
3236 This command creates a symbolic link using the C<ln -s> command.");
3238 ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3239 [InitBasicFS, Always, TestOutput (
3240 [["mkdir_p"; "/a/b"];
3241 ["touch"; "/a/b/c"];
3242 ["ln_sf"; "../d"; "/a/b/c"];
3243 ["readlink"; "/a/b/c"]], "../d")],
3244 "create a symbolic link",
3246 This command creates a symbolic link using the C<ln -sf> command,
3247 The C<-f> option removes the link (C<linkname>) if it exists already.");
3249 ("readlink", (RString "link", [Pathname "path"]), 168, [],
3250 [] (* XXX tested above *),
3251 "read the target of a symbolic link",
3253 This command reads the target of a symbolic link.");
3255 ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3256 [InitBasicFS, Always, TestOutputStruct (
3257 [["fallocate"; "/a"; "1000000"];
3258 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3259 "preallocate a file in the guest filesystem",
3261 This command preallocates a file (containing zero bytes) named
3262 C<path> of size C<len> bytes. If the file exists already, it
3265 Do not confuse this with the guestfish-specific
3266 C<alloc> command which allocates a file in the host and
3267 attaches it as a device.");
3269 ("swapon_device", (RErr, [Device "device"]), 170, [],
3270 [InitPartition, Always, TestRun (
3271 [["mkswap"; "/dev/sda1"];
3272 ["swapon_device"; "/dev/sda1"];
3273 ["swapoff_device"; "/dev/sda1"]])],
3274 "enable swap on device",
3276 This command enables the libguestfs appliance to use the
3277 swap device or partition named C<device>. The increased
3278 memory is made available for all commands, for example
3279 those run using C<guestfs_command> or C<guestfs_sh>.
3281 Note that you should not swap to existing guest swap
3282 partitions unless you know what you are doing. They may
3283 contain hibernation information, or other information that
3284 the guest doesn't want you to trash. You also risk leaking
3285 information about the host to the guest this way. Instead,
3286 attach a new host device to the guest and swap on that.");
3288 ("swapoff_device", (RErr, [Device "device"]), 171, [],
3289 [], (* XXX tested by swapon_device *)
3290 "disable swap on device",
3292 This command disables the libguestfs appliance swap
3293 device or partition named C<device>.
3294 See C<guestfs_swapon_device>.");
3296 ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3297 [InitBasicFS, Always, TestRun (
3298 [["fallocate"; "/swap"; "8388608"];
3299 ["mkswap_file"; "/swap"];
3300 ["swapon_file"; "/swap"];
3301 ["swapoff_file"; "/swap"]])],
3302 "enable swap on file",
3304 This command enables swap to a file.
3305 See C<guestfs_swapon_device> for other notes.");
3307 ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3308 [], (* XXX tested by swapon_file *)
3309 "disable swap on file",
3311 This command disables the libguestfs appliance swap on file.");
3313 ("swapon_label", (RErr, [String "label"]), 174, [],
3314 [InitEmpty, Always, TestRun (
3315 [["sfdiskM"; "/dev/sdb"; ","];
3316 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3317 ["swapon_label"; "swapit"];
3318 ["swapoff_label"; "swapit"];
3319 ["zero"; "/dev/sdb"];
3320 ["blockdev_rereadpt"; "/dev/sdb"]])],
3321 "enable swap on labeled swap partition",
3323 This command enables swap to a labeled swap partition.
3324 See C<guestfs_swapon_device> for other notes.");
3326 ("swapoff_label", (RErr, [String "label"]), 175, [],
3327 [], (* XXX tested by swapon_label *)
3328 "disable swap on labeled swap partition",
3330 This command disables the libguestfs appliance swap on
3331 labeled swap partition.");
3333 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3334 (let uuid = uuidgen () in
3335 [InitEmpty, Always, TestRun (
3336 [["mkswap_U"; uuid; "/dev/sdb"];
3337 ["swapon_uuid"; uuid];
3338 ["swapoff_uuid"; uuid]])]),
3339 "enable swap on swap partition by UUID",
3341 This command enables swap to a swap partition with the given UUID.
3342 See C<guestfs_swapon_device> for other notes.");
3344 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3345 [], (* XXX tested by swapon_uuid *)
3346 "disable swap on swap partition by UUID",
3348 This command disables the libguestfs appliance swap partition
3349 with the given UUID.");
3351 ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3352 [InitBasicFS, Always, TestRun (
3353 [["fallocate"; "/swap"; "8388608"];
3354 ["mkswap_file"; "/swap"]])],
3355 "create a swap file",
3359 This command just writes a swap file signature to an existing
3360 file. To create the file itself, use something like C<guestfs_fallocate>.");
3362 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3363 [InitSquashFS, Always, TestRun (
3364 [["inotify_init"; "0"]])],
3365 "create an inotify handle",
3367 This command creates a new inotify handle.
3368 The inotify subsystem can be used to notify events which happen to
3369 objects in the guest filesystem.
3371 C<maxevents> is the maximum number of events which will be
3372 queued up between calls to C<guestfs_inotify_read> or
3373 C<guestfs_inotify_files>.
3374 If this is passed as C<0>, then the kernel (or previously set)
3375 default is used. For Linux 2.6.29 the default was 16384 events.
3376 Beyond this limit, the kernel throws away events, but records
3377 the fact that it threw them away by setting a flag
3378 C<IN_Q_OVERFLOW> in the returned structure list (see
3379 C<guestfs_inotify_read>).
3381 Before any events are generated, you have to add some
3382 watches to the internal watch list. See:
3383 C<guestfs_inotify_add_watch>,
3384 C<guestfs_inotify_rm_watch> and
3385 C<guestfs_inotify_watch_all>.
3387 Queued up events should be read periodically by calling
3388 C<guestfs_inotify_read>
3389 (or C<guestfs_inotify_files> which is just a helpful
3390 wrapper around C<guestfs_inotify_read>). If you don't
3391 read the events out often enough then you risk the internal
3394 The handle should be closed after use by calling
3395 C<guestfs_inotify_close>. This also removes any
3396 watches automatically.
3398 See also L<inotify(7)> for an overview of the inotify interface
3399 as exposed by the Linux kernel, which is roughly what we expose
3400 via libguestfs. Note that there is one global inotify handle
3401 per libguestfs instance.");
3403 ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3404 [InitBasicFS, Always, TestOutputList (
3405 [["inotify_init"; "0"];
3406 ["inotify_add_watch"; "/"; "1073741823"];
3409 ["inotify_files"]], ["a"; "b"])],
3410 "add an inotify watch",
3412 Watch C<path> for the events listed in C<mask>.
3414 Note that if C<path> is a directory then events within that
3415 directory are watched, but this does I<not> happen recursively
3416 (in subdirectories).
3418 Note for non-C or non-Linux callers: the inotify events are
3419 defined by the Linux kernel ABI and are listed in
3420 C</usr/include/sys/inotify.h>.");
3422 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3424 "remove an inotify watch",
3426 Remove a previously defined inotify watch.
3427 See C<guestfs_inotify_add_watch>.");
3429 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3431 "return list of inotify events",
3433 Return the complete queue of events that have happened
3434 since the previous read call.
3436 If no events have happened, this returns an empty list.
3438 I<Note>: In order to make sure that all events have been
3439 read, you must call this function repeatedly until it
3440 returns an empty list. The reason is that the call will
3441 read events up to the maximum appliance-to-host message
3442 size and leave remaining events in the queue.");
3444 ("inotify_files", (RStringList "paths", []), 183, [],
3446 "return list of watched files that had events",
3448 This function is a helpful wrapper around C<guestfs_inotify_read>
3449 which just returns a list of pathnames of objects that were
3450 touched. The returned pathnames are sorted and deduplicated.");
3452 ("inotify_close", (RErr, []), 184, [],
3454 "close the inotify handle",
3456 This closes the inotify handle which was previously
3457 opened by inotify_init. It removes all watches, throws
3458 away any pending events, and deallocates all resources.");
3460 ("setcon", (RErr, [String "context"]), 185, [],
3462 "set SELinux security context",
3464 This sets the SELinux security context of the daemon
3465 to the string C<context>.
3467 See the documentation about SELINUX in L<guestfs(3)>.");
3469 ("getcon", (RString "context", []), 186, [],
3471 "get SELinux security context",
3473 This gets the SELinux security context of the daemon.
3475 See the documentation about SELINUX in L<guestfs(3)>,
3476 and C<guestfs_setcon>");
3478 ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3479 [InitEmpty, Always, TestOutput (
3480 [["sfdiskM"; "/dev/sda"; ","];
3481 ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3482 ["mount"; "/dev/sda1"; "/"];
3483 ["write_file"; "/new"; "new file contents"; "0"];
3484 ["cat"; "/new"]], "new file contents")],
3485 "make a filesystem with block size",
3487 This call is similar to C<guestfs_mkfs>, but it allows you to
3488 control the block size of the resulting filesystem. Supported
3489 block sizes depend on the filesystem type, but typically they
3490 are C<1024>, C<2048> or C<4096> only.");
3492 ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3493 [InitEmpty, Always, TestOutput (
3494 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3495 ["mke2journal"; "4096"; "/dev/sda1"];
3496 ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3497 ["mount"; "/dev/sda2"; "/"];
3498 ["write_file"; "/new"; "new file contents"; "0"];
3499 ["cat"; "/new"]], "new file contents")],
3500 "make ext2/3/4 external journal",
3502 This creates an ext2 external journal on C<device>. It is equivalent
3505 mke2fs -O journal_dev -b blocksize device");
3507 ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3508 [InitEmpty, Always, TestOutput (
3509 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3510 ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3511 ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3512 ["mount"; "/dev/sda2"; "/"];
3513 ["write_file"; "/new"; "new file contents"; "0"];
3514 ["cat"; "/new"]], "new file contents")],
3515 "make ext2/3/4 external journal with label",
3517 This creates an ext2 external journal on C<device> with label C<label>.");
3519 ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3520 (let uuid = uuidgen () in
3521 [InitEmpty, Always, TestOutput (
3522 [["sfdiskM"; "/dev/sda"; ",100 ,"];
3523 ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3524 ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3525 ["mount"; "/dev/sda2"; "/"];
3526 ["write_file"; "/new"; "new file contents"; "0"];
3527 ["cat"; "/new"]], "new file contents")]),
3528 "make ext2/3/4 external journal with UUID",
3530 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3532 ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3534 "make ext2/3/4 filesystem with external journal",
3536 This creates an ext2/3/4 filesystem on C<device> with
3537 an external journal on C<journal>. It is equivalent
3540 mke2fs -t fstype -b blocksize -J device=<journal> <device>
3542 See also C<guestfs_mke2journal>.");
3544 ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3546 "make ext2/3/4 filesystem with external journal",
3548 This creates an ext2/3/4 filesystem on C<device> with
3549 an external journal on the journal labeled C<label>.
3551 See also C<guestfs_mke2journal_L>.");
3553 ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3555 "make ext2/3/4 filesystem with external journal",
3557 This creates an ext2/3/4 filesystem on C<device> with
3558 an external journal on the journal with UUID C<uuid>.
3560 See also C<guestfs_mke2journal_U>.");
3564 let all_functions = non_daemon_functions @ daemon_functions
3566 (* In some places we want the functions to be displayed sorted
3567 * alphabetically, so this is useful:
3569 let all_functions_sorted =
3570 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3571 compare n1 n2) all_functions
3573 (* Field types for structures. *)
3575 | FChar (* C 'char' (really, a 7 bit byte). *)
3576 | FString (* nul-terminated ASCII string, NOT NULL. *)
3577 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3582 | FBytes (* Any int measure that counts bytes. *)
3583 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3584 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3586 (* Because we generate extra parsing code for LVM command line tools,
3587 * we have to pull out the LVM columns separately here.
3597 "pv_attr", FString (* XXX *);
3598 "pv_pe_count", FInt64;
3599 "pv_pe_alloc_count", FInt64;
3602 "pv_mda_count", FInt64;
3603 "pv_mda_free", FBytes;
3604 (* Not in Fedora 10:
3605 "pv_mda_size", FBytes;
3612 "vg_attr", FString (* XXX *);
3615 "vg_sysid", FString;
3616 "vg_extent_size", FBytes;
3617 "vg_extent_count", FInt64;
3618 "vg_free_count", FInt64;
3623 "snap_count", FInt64;
3626 "vg_mda_count", FInt64;
3627 "vg_mda_free", FBytes;
3628 (* Not in Fedora 10:
3629 "vg_mda_size", FBytes;
3635 "lv_attr", FString (* XXX *);
3638 "lv_kernel_major", FInt64;
3639 "lv_kernel_minor", FInt64;
3641 "seg_count", FInt64;
3643 "snap_percent", FOptPercent;
3644 "copy_percent", FOptPercent;
3647 "mirror_log", FString;
3651 (* Names and fields in all structures (in RStruct and RStructList)
3655 (* The old RIntBool return type, only ever used for aug_defnode. Do
3656 * not use this struct in any new code.
3659 "i", FInt32; (* for historical compatibility *)
3660 "b", FInt32; (* for historical compatibility *)
3663 (* LVM PVs, VGs, LVs. *)
3664 "lvm_pv", lvm_pv_cols;
3665 "lvm_vg", lvm_vg_cols;
3666 "lvm_lv", lvm_lv_cols;
3668 (* Column names and types from stat structures.
3669 * NB. Can't use things like 'st_atime' because glibc header files
3670 * define some of these as macros. Ugh.
3701 (* Column names in dirent structure. *)
3704 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3709 (* Version numbers. *)
3717 (* Extended attribute. *)
3719 "attrname", FString;
3723 (* Inotify events. *)
3727 "in_cookie", FUInt32;
3730 ] (* end of structs *)
3732 (* Ugh, Java has to be different ..
3733 * These names are also used by the Haskell bindings.
3735 let java_structs = [
3736 "int_bool", "IntBool";
3741 "statvfs", "StatVFS";
3743 "version", "Version";
3745 "inotify_event", "INotifyEvent";
3748 (* What structs are actually returned. *)
3749 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3751 (* Returns a list of RStruct/RStructList structs that are returned
3752 * by any function. Each element of returned list is a pair:
3754 * (structname, RStructOnly)
3755 * == there exists function which returns RStruct (_, structname)
3756 * (structname, RStructListOnly)
3757 * == there exists function which returns RStructList (_, structname)
3758 * (structname, RStructAndList)
3759 * == there are functions returning both RStruct (_, structname)
3760 * and RStructList (_, structname)
3763 (* ||| is a "logical OR" for rstructs_used_t *)
3767 | _, RStructAndList -> RStructAndList
3768 | RStructOnly, RStructListOnly
3769 | RStructListOnly, RStructOnly -> RStructAndList
3770 | RStructOnly, RStructOnly -> RStructOnly
3771 | RStructListOnly, RStructListOnly -> RStructListOnly
3774 let h = Hashtbl.create 13 in
3776 (* if elem->oldv exists, update entry using ||| operator,
3777 * else just add elem->newv to the hash
3779 let update elem newv =
3780 try let oldv = Hashtbl.find h elem in
3781 Hashtbl.replace h elem (newv ||| oldv)
3782 with Not_found -> Hashtbl.add h elem newv
3786 fun (_, style, _, _, _, _, _) ->
3787 match fst style with
3788 | RStruct (_, structname) -> update structname RStructOnly
3789 | RStructList (_, structname) -> update structname RStructListOnly
3793 (* return key->values as a list of (key,value) *)
3794 Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3800 | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3801 | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3802 | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3806 (* Used for testing language bindings. *)
3808 | CallString of string
3809 | CallOptString of string option
3810 | CallStringList of string list
3814 (* Used to memoize the result of pod2text. *)
3815 let pod2text_memo_filename = "src/.pod2text.data"
3816 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3818 let chan = open_in pod2text_memo_filename in
3819 let v = input_value chan in
3823 _ -> Hashtbl.create 13
3825 (* Useful functions.
3826 * Note we don't want to use any external OCaml libraries which
3827 * makes this a bit harder than it should be.
3829 let failwithf fs = ksprintf failwith fs
3831 let replace_char s c1 c2 =
3832 let s2 = String.copy s in
3833 let r = ref false in
3834 for i = 0 to String.length s2 - 1 do
3835 if String.unsafe_get s2 i = c1 then (
3836 String.unsafe_set s2 i c2;
3840 if not !r then s else s2
3844 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3846 let triml ?(test = isspace) str =
3848 let n = ref (String.length str) in
3849 while !n > 0 && test str.[!i]; do
3854 else String.sub str !i !n
3856 let trimr ?(test = isspace) str =
3857 let n = ref (String.length str) in
3858 while !n > 0 && test str.[!n-1]; do
3861 if !n = String.length str then str
3862 else String.sub str 0 !n
3864 let trim ?(test = isspace) str =
3865 trimr ~test (triml ~test str)
3867 let rec find s sub =
3868 let len = String.length s in
3869 let sublen = String.length sub in
3871 if i <= len-sublen then (
3873 if j < sublen then (
3874 if s.[i+j] = sub.[j] then loop2 (j+1)
3880 if r = -1 then loop (i+1) else r
3886 let rec replace_str s s1 s2 =
3887 let len = String.length s in
3888 let sublen = String.length s1 in
3889 let i = find s s1 in
3892 let s' = String.sub s 0 i in
3893 let s'' = String.sub s (i+sublen) (len-i-sublen) in
3894 s' ^ s2 ^ replace_str s'' s1 s2
3897 let rec string_split sep str =
3898 let len = String.length str in
3899 let seplen = String.length sep in
3900 let i = find str sep in
3901 if i = -1 then [str]
3903 let s' = String.sub str 0 i in
3904 let s'' = String.sub str (i+seplen) (len-i-seplen) in
3905 s' :: string_split sep s''
3908 let files_equal n1 n2 =
3909 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3910 match Sys.command cmd with
3913 | i -> failwithf "%s: failed with error code %d" cmd i
3915 let rec filter_map f = function
3919 | Some y -> y :: filter_map f xs
3920 | None -> filter_map f xs
3922 let rec find_map f = function
3923 | [] -> raise Not_found
3927 | None -> find_map f xs
3930 let rec loop i = function
3932 | x :: xs -> f i x; loop (i+1) xs
3937 let rec loop i = function
3939 | x :: xs -> let r = f i x in r :: loop (i+1) xs
3943 let name_of_argt = function
3944 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | Bool n | Int n
3945 | FileIn n | FileOut n -> n
3947 let java_name_of_struct typ =
3948 try List.assoc typ java_structs
3951 "java_name_of_struct: no java_structs entry corresponding to %s" typ
3953 let cols_of_struct typ =
3954 try List.assoc typ structs
3956 failwithf "cols_of_struct: unknown struct %s" typ
3958 let seq_of_test = function
3959 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3960 | TestOutputListOfDevices (s, _)
3961 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3962 | TestOutputTrue s | TestOutputFalse s
3963 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3964 | TestOutputStruct (s, _)
3965 | TestLastFail s -> s
3967 (* Handling for function flags. *)
3968 let protocol_limit_warning =
3969 "Because of the message protocol, there is a transfer limit
3970 of somewhere between 2MB and 4MB. To transfer large files you should use
3973 let danger_will_robinson =
3974 "B<This command is dangerous. Without careful use you
3975 can easily destroy all your data>."
3977 let deprecation_notice flags =
3980 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
3982 sprintf "This function is deprecated.
3983 In new code, use the C<%s> call instead.
3985 Deprecated functions will not be removed from the API, but the
3986 fact that they are deprecated indicates that there are problems
3987 with correct use of these functions." alt in
3992 (* Check function names etc. for consistency. *)
3993 let check_functions () =
3994 let contains_uppercase str =
3995 let len = String.length str in
3997 if i >= len then false
4000 if c >= 'A' && c <= 'Z' then true
4007 (* Check function names. *)
4009 fun (name, _, _, _, _, _, _) ->
4010 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4011 failwithf "function name %s does not need 'guestfs' prefix" name;
4013 failwithf "function name is empty";
4014 if name.[0] < 'a' || name.[0] > 'z' then
4015 failwithf "function name %s must start with lowercase a-z" name;
4016 if String.contains name '-' then
4017 failwithf "function name %s should not contain '-', use '_' instead."
4021 (* Check function parameter/return names. *)
4023 fun (name, style, _, _, _, _, _) ->
4024 let check_arg_ret_name n =
4025 if contains_uppercase n then
4026 failwithf "%s param/ret %s should not contain uppercase chars"
4028 if String.contains n '-' || String.contains n '_' then
4029 failwithf "%s param/ret %s should not contain '-' or '_'"
4032 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;
4033 if n = "int" || n = "char" || n = "short" || n = "long" then
4034 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4035 if n = "i" || n = "n" then
4036 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4037 if n = "argv" || n = "args" then
4038 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
4041 (match fst style with
4043 | RInt n | RInt64 n | RBool n
4044 | RConstString n | RConstOptString n | RString n
4045 | RStringList n | RStruct (n, _) | RStructList (n, _)
4046 | RHashtable n | RBufferOut n ->
4047 check_arg_ret_name n
4049 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4052 (* Check short descriptions. *)
4054 fun (name, _, _, _, _, shortdesc, _) ->
4055 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4056 failwithf "short description of %s should begin with lowercase." name;
4057 let c = shortdesc.[String.length shortdesc-1] in
4058 if c = '\n' || c = '.' then
4059 failwithf "short description of %s should not end with . or \\n." name
4062 (* Check long dscriptions. *)
4064 fun (name, _, _, _, _, _, longdesc) ->
4065 if longdesc.[String.length longdesc-1] = '\n' then
4066 failwithf "long description of %s should not end with \\n." name
4069 (* Check proc_nrs. *)
4071 fun (name, _, proc_nr, _, _, _, _) ->
4072 if proc_nr <= 0 then
4073 failwithf "daemon function %s should have proc_nr > 0" name
4077 fun (name, _, proc_nr, _, _, _, _) ->
4078 if proc_nr <> -1 then
4079 failwithf "non-daemon function %s should have proc_nr -1" name
4080 ) non_daemon_functions;
4083 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4086 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4087 let rec loop = function
4090 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4092 | (name1,nr1) :: (name2,nr2) :: _ ->
4093 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4101 (* Ignore functions that have no tests. We generate a
4102 * warning when the user does 'make check' instead.
4104 | name, _, _, _, [], _, _ -> ()
4105 | name, _, _, _, tests, _, _ ->
4109 match seq_of_test test with
4111 failwithf "%s has a test containing an empty sequence" name
4112 | cmds -> List.map List.hd cmds
4114 let funcs = List.flatten funcs in
4116 let tested = List.mem name funcs in
4119 failwithf "function %s has tests but does not test itself" name
4122 (* 'pr' prints to the current output file. *)
4123 let chan = ref stdout
4124 let pr fs = ksprintf (output_string !chan) fs
4126 (* Generate a header block in a number of standard styles. *)
4127 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4128 type license = GPLv2 | LGPLv2
4130 let generate_header comment license =
4131 let c = match comment with
4132 | CStyle -> pr "/* "; " *"
4133 | HashStyle -> pr "# "; "#"
4134 | OCamlStyle -> pr "(* "; " *"
4135 | HaskellStyle -> pr "{- "; " " in
4136 pr "libguestfs generated file\n";
4137 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4138 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4140 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4144 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4145 pr "%s it under the terms of the GNU General Public License as published by\n" c;
4146 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4147 pr "%s (at your option) any later version.\n" c;
4149 pr "%s This program is distributed in the hope that it will be useful,\n" c;
4150 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4151 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
4152 pr "%s GNU General Public License for more details.\n" c;
4154 pr "%s You should have received a copy of the GNU General Public License along\n" c;
4155 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4156 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4159 pr "%s This library is free software; you can redistribute it and/or\n" c;
4160 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4161 pr "%s License as published by the Free Software Foundation; either\n" c;
4162 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4164 pr "%s This library is distributed in the hope that it will be useful,\n" c;
4165 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4166 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
4167 pr "%s Lesser General Public License for more details.\n" c;
4169 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4170 pr "%s License along with this library; if not, write to the Free Software\n" c;
4171 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4174 | CStyle -> pr " */\n"
4176 | OCamlStyle -> pr " *)\n"
4177 | HaskellStyle -> pr "-}\n"
4181 (* Start of main code generation functions below this line. *)
4183 (* Generate the pod documentation for the C API. *)
4184 let rec generate_actions_pod () =
4186 fun (shortname, style, _, flags, _, _, longdesc) ->
4187 if not (List.mem NotInDocs flags) then (
4188 let name = "guestfs_" ^ shortname in
4189 pr "=head2 %s\n\n" name;
4191 generate_prototype ~extern:false ~handle:"handle" name style;
4193 pr "%s\n\n" longdesc;
4194 (match fst style with
4196 pr "This function returns 0 on success or -1 on error.\n\n"
4198 pr "On error this function returns -1.\n\n"
4200 pr "On error this function returns -1.\n\n"
4202 pr "This function returns a C truth value on success or -1 on error.\n\n"
4204 pr "This function returns a string, or NULL on error.
4205 The string is owned by the guest handle and must I<not> be freed.\n\n"
4206 | RConstOptString _ ->
4207 pr "This function returns a string which may be NULL.
4208 There is way to return an error from this function.
4209 The string is owned by the guest handle and must I<not> be freed.\n\n"
4211 pr "This function returns a string, or NULL on error.
4212 I<The caller must free the returned string after use>.\n\n"
4214 pr "This function returns a NULL-terminated array of strings
4215 (like L<environ(3)>), or NULL if there was an error.
4216 I<The caller must free the strings and the array after use>.\n\n"
4217 | RStruct (_, typ) ->
4218 pr "This function returns a C<struct guestfs_%s *>,
4219 or NULL if there was an error.
4220 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4221 | RStructList (_, typ) ->
4222 pr "This function returns a C<struct guestfs_%s_list *>
4223 (see E<lt>guestfs-structs.hE<gt>),
4224 or NULL if there was an error.
4225 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4227 pr "This function returns a NULL-terminated array of
4228 strings, or NULL if there was an error.
4229 The array of strings will always have length C<2n+1>, where
4230 C<n> keys and values alternate, followed by the trailing NULL entry.
4231 I<The caller must free the strings and the array after use>.\n\n"
4233 pr "This function returns a buffer, or NULL on error.
4234 The size of the returned buffer is written to C<*size_r>.
4235 I<The caller must free the returned buffer after use>.\n\n"
4237 if List.mem ProtocolLimitWarning flags then
4238 pr "%s\n\n" protocol_limit_warning;
4239 if List.mem DangerWillRobinson flags then
4240 pr "%s\n\n" danger_will_robinson;
4241 match deprecation_notice flags with
4243 | Some txt -> pr "%s\n\n" txt
4245 ) all_functions_sorted
4247 and generate_structs_pod () =
4248 (* Structs documentation. *)
4251 pr "=head2 guestfs_%s\n" typ;
4253 pr " struct guestfs_%s {\n" typ;
4256 | name, FChar -> pr " char %s;\n" name
4257 | name, FUInt32 -> pr " uint32_t %s;\n" name
4258 | name, FInt32 -> pr " int32_t %s;\n" name
4259 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4260 | name, FInt64 -> pr " int64_t %s;\n" name
4261 | name, FString -> pr " char *%s;\n" name
4263 pr " /* The next two fields describe a byte array. */\n";
4264 pr " uint32_t %s_len;\n" name;
4265 pr " char *%s;\n" name
4267 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4268 pr " char %s[32];\n" name
4269 | name, FOptPercent ->
4270 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4271 pr " float %s;\n" name
4275 pr " struct guestfs_%s_list {\n" typ;
4276 pr " uint32_t len; /* Number of elements in list. */\n";
4277 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4280 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4281 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4286 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4287 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4289 * We have to use an underscore instead of a dash because otherwise
4290 * rpcgen generates incorrect code.
4292 * This header is NOT exported to clients, but see also generate_structs_h.
4294 and generate_xdr () =
4295 generate_header CStyle LGPLv2;
4297 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4298 pr "typedef string str<>;\n";
4301 (* Internal structures. *)
4305 pr "struct guestfs_int_%s {\n" typ;
4307 | name, FChar -> pr " char %s;\n" name
4308 | name, FString -> pr " string %s<>;\n" name
4309 | name, FBuffer -> pr " opaque %s<>;\n" name
4310 | name, FUUID -> pr " opaque %s[32];\n" name
4311 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4312 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4313 | name, FOptPercent -> pr " float %s;\n" name
4317 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4322 fun (shortname, style, _, _, _, _, _) ->
4323 let name = "guestfs_" ^ shortname in
4325 (match snd style with
4328 pr "struct %s_args {\n" name;
4331 | Pathname n | Device n | Dev_or_Path n | String n -> pr " string %s<>;\n" n
4332 | OptString n -> pr " str *%s;\n" n
4333 | StringList n -> pr " str %s<>;\n" n
4334 | Bool n -> pr " bool %s;\n" n
4335 | Int n -> pr " int %s;\n" n
4336 | FileIn _ | FileOut _ -> ()
4340 (match fst style with
4343 pr "struct %s_ret {\n" name;
4347 pr "struct %s_ret {\n" name;
4348 pr " hyper %s;\n" n;
4351 pr "struct %s_ret {\n" name;
4354 | RConstString _ | RConstOptString _ ->
4355 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4357 pr "struct %s_ret {\n" name;
4358 pr " string %s<>;\n" n;
4361 pr "struct %s_ret {\n" name;
4362 pr " str %s<>;\n" n;
4364 | RStruct (n, typ) ->
4365 pr "struct %s_ret {\n" name;
4366 pr " guestfs_int_%s %s;\n" typ n;
4368 | RStructList (n, typ) ->
4369 pr "struct %s_ret {\n" name;
4370 pr " guestfs_int_%s_list %s;\n" typ n;
4373 pr "struct %s_ret {\n" name;
4374 pr " str %s<>;\n" n;
4377 pr "struct %s_ret {\n" name;
4378 pr " opaque %s<>;\n" n;
4383 (* Table of procedure numbers. *)
4384 pr "enum guestfs_procedure {\n";
4386 fun (shortname, _, proc_nr, _, _, _, _) ->
4387 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4389 pr " GUESTFS_PROC_NR_PROCS\n";
4393 (* Having to choose a maximum message size is annoying for several
4394 * reasons (it limits what we can do in the API), but it (a) makes
4395 * the protocol a lot simpler, and (b) provides a bound on the size
4396 * of the daemon which operates in limited memory space. For large
4397 * file transfers you should use FTP.
4399 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4402 (* Message header, etc. *)
4404 /* The communication protocol is now documented in the guestfs(3)
4408 const GUESTFS_PROGRAM = 0x2000F5F5;
4409 const GUESTFS_PROTOCOL_VERSION = 1;
4411 /* These constants must be larger than any possible message length. */
4412 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4413 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4415 enum guestfs_message_direction {
4416 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4417 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4420 enum guestfs_message_status {
4421 GUESTFS_STATUS_OK = 0,
4422 GUESTFS_STATUS_ERROR = 1
4425 const GUESTFS_ERROR_LEN = 256;
4427 struct guestfs_message_error {
4428 string error_message<GUESTFS_ERROR_LEN>;
4431 struct guestfs_message_header {
4432 unsigned prog; /* GUESTFS_PROGRAM */
4433 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4434 guestfs_procedure proc; /* GUESTFS_PROC_x */
4435 guestfs_message_direction direction;
4436 unsigned serial; /* message serial number */
4437 guestfs_message_status status;
4440 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4442 struct guestfs_chunk {
4443 int cancel; /* if non-zero, transfer is cancelled */
4444 /* data size is 0 bytes if the transfer has finished successfully */
4445 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4449 (* Generate the guestfs-structs.h file. *)
4450 and generate_structs_h () =
4451 generate_header CStyle LGPLv2;
4453 (* This is a public exported header file containing various
4454 * structures. The structures are carefully written to have
4455 * exactly the same in-memory format as the XDR structures that
4456 * we use on the wire to the daemon. The reason for creating
4457 * copies of these structures here is just so we don't have to
4458 * export the whole of guestfs_protocol.h (which includes much
4459 * unrelated and XDR-dependent stuff that we don't want to be
4460 * public, or required by clients).
4462 * To reiterate, we will pass these structures to and from the
4463 * client with a simple assignment or memcpy, so the format
4464 * must be identical to what rpcgen / the RFC defines.
4467 (* Public structures. *)
4470 pr "struct guestfs_%s {\n" typ;
4473 | name, FChar -> pr " char %s;\n" name
4474 | name, FString -> pr " char *%s;\n" name
4476 pr " uint32_t %s_len;\n" name;
4477 pr " char *%s;\n" name
4478 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4479 | name, FUInt32 -> pr " uint32_t %s;\n" name
4480 | name, FInt32 -> pr " int32_t %s;\n" name
4481 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4482 | name, FInt64 -> pr " int64_t %s;\n" name
4483 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4487 pr "struct guestfs_%s_list {\n" typ;
4488 pr " uint32_t len;\n";
4489 pr " struct guestfs_%s *val;\n" typ;
4492 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4493 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4497 (* Generate the guestfs-actions.h file. *)
4498 and generate_actions_h () =
4499 generate_header CStyle LGPLv2;
4501 fun (shortname, style, _, _, _, _, _) ->
4502 let name = "guestfs_" ^ shortname in
4503 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4507 (* Generate the client-side dispatch stubs. *)
4508 and generate_client_actions () =
4509 generate_header CStyle LGPLv2;
4515 #include \"guestfs.h\"
4516 #include \"guestfs_protocol.h\"
4518 #define error guestfs_error
4519 #define perrorf guestfs_perrorf
4520 #define safe_malloc guestfs_safe_malloc
4521 #define safe_realloc guestfs_safe_realloc
4522 #define safe_strdup guestfs_safe_strdup
4523 #define safe_memdup guestfs_safe_memdup
4525 /* Check the return message from a call for validity. */
4527 check_reply_header (guestfs_h *g,
4528 const struct guestfs_message_header *hdr,
4529 int proc_nr, int serial)
4531 if (hdr->prog != GUESTFS_PROGRAM) {
4532 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4535 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4536 error (g, \"wrong protocol version (%%d/%%d)\",
4537 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4540 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4541 error (g, \"unexpected message direction (%%d/%%d)\",
4542 hdr->direction, GUESTFS_DIRECTION_REPLY);
4545 if (hdr->proc != proc_nr) {
4546 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4549 if (hdr->serial != serial) {
4550 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4557 /* Check we are in the right state to run a high-level action. */
4559 check_state (guestfs_h *g, const char *caller)
4561 if (!guestfs_is_ready (g)) {
4562 if (guestfs_is_config (g))
4563 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4565 else if (guestfs_is_launching (g))
4566 error (g, \"%%s: call wait_ready() before using this function\",
4569 error (g, \"%%s called from the wrong state, %%d != READY\",
4570 caller, guestfs_get_state (g));
4578 (* Client-side stubs for each function. *)
4580 fun (shortname, style, _, _, _, _, _) ->
4581 let name = "guestfs_" ^ shortname in
4583 (* Generate the context struct which stores the high-level
4584 * state between callback functions.
4586 pr "struct %s_ctx {\n" shortname;
4587 pr " /* This flag is set by the callbacks, so we know we've done\n";
4588 pr " * the callbacks as expected, and in the right sequence.\n";
4589 pr " * 0 = not called, 1 = reply_cb called.\n";
4591 pr " int cb_sequence;\n";
4592 pr " struct guestfs_message_header hdr;\n";
4593 pr " struct guestfs_message_error err;\n";
4594 (match fst style with
4596 | RConstString _ | RConstOptString _ ->
4597 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4599 | RBool _ | RString _ | RStringList _
4600 | RStruct _ | RStructList _
4601 | RHashtable _ | RBufferOut _ ->
4602 pr " struct %s_ret ret;\n" name
4607 (* Generate the reply callback function. *)
4608 pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4610 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4611 pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4613 pr " /* This should definitely not happen. */\n";
4614 pr " if (ctx->cb_sequence != 0) {\n";
4615 pr " ctx->cb_sequence = 9999;\n";
4616 pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4620 pr " ml->main_loop_quit (ml, g);\n";
4622 pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4623 pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4626 pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4627 pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4628 pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4635 (match fst style with
4637 | RConstString _ | RConstOptString _ ->
4638 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4640 | RBool _ | RString _ | RStringList _
4641 | RStruct _ | RStructList _
4642 | RHashtable _ | RBufferOut _ ->
4643 pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4644 pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4650 pr " ctx->cb_sequence = 1;\n";
4653 (* Generate the action stub. *)
4654 generate_prototype ~extern:false ~semicolon:false ~newline:true
4655 ~handle:"g" name style;
4658 match fst style with
4659 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4660 | RConstString _ | RConstOptString _ ->
4661 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4662 | RString _ | RStringList _
4663 | RStruct _ | RStructList _
4664 | RHashtable _ | RBufferOut _ ->
4669 (match snd style with
4671 | _ -> pr " struct %s_args args;\n" name
4674 pr " struct %s_ctx ctx;\n" shortname;
4675 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4676 pr " int serial;\n";
4678 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4679 pr " guestfs_set_busy (g);\n";
4681 pr " memset (&ctx, 0, sizeof ctx);\n";
4684 (* Send the main header and arguments. *)
4685 (match snd style with
4687 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4688 (String.uppercase shortname)
4692 | Pathname n | Device n | Dev_or_Path n | String n ->
4693 pr " args.%s = (char *) %s;\n" n n
4695 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
4697 pr " args.%s.%s_val = (char **) %s;\n" n n n;
4698 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4700 pr " args.%s = %s;\n" n n
4702 pr " args.%s = %s;\n" n n
4703 | FileIn _ | FileOut _ -> ()
4705 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4706 (String.uppercase shortname);
4707 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4710 pr " if (serial == -1) {\n";
4711 pr " guestfs_end_busy (g);\n";
4712 pr " return %s;\n" error_code;
4716 (* Send any additional files (FileIn) requested. *)
4717 let need_read_reply_label = ref false in
4724 pr " r = guestfs__send_file_sync (g, %s);\n" n;
4725 pr " if (r == -1) {\n";
4726 pr " guestfs_end_busy (g);\n";
4727 pr " return %s;\n" error_code;
4729 pr " if (r == -2) /* daemon cancelled */\n";
4730 pr " goto read_reply;\n";
4731 need_read_reply_label := true;
4737 (* Wait for the reply from the remote end. *)
4738 if !need_read_reply_label then pr " read_reply:\n";
4739 pr " guestfs__switch_to_receiving (g);\n";
4740 pr " ctx.cb_sequence = 0;\n";
4741 pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4742 pr " (void) ml->main_loop_run (ml, g);\n";
4743 pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
4744 pr " if (ctx.cb_sequence != 1) {\n";
4745 pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4746 pr " guestfs_end_busy (g);\n";
4747 pr " return %s;\n" error_code;
4751 pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4752 (String.uppercase shortname);
4753 pr " guestfs_end_busy (g);\n";
4754 pr " return %s;\n" error_code;
4758 pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4759 pr " error (g, \"%%s\", ctx.err.error_message);\n";
4760 pr " free (ctx.err.error_message);\n";
4761 pr " guestfs_end_busy (g);\n";
4762 pr " return %s;\n" error_code;
4766 (* Expecting to receive further files (FileOut)? *)
4770 pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4771 pr " guestfs_end_busy (g);\n";
4772 pr " return %s;\n" error_code;
4778 pr " guestfs_end_busy (g);\n";
4780 (match fst style with
4781 | RErr -> pr " return 0;\n"
4782 | RInt n | RInt64 n | RBool n ->
4783 pr " return ctx.ret.%s;\n" n
4784 | RConstString _ | RConstOptString _ ->
4785 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4787 pr " return ctx.ret.%s; /* caller will free */\n" n
4788 | RStringList n | RHashtable n ->
4789 pr " /* caller will free this, but we need to add a NULL entry */\n";
4790 pr " ctx.ret.%s.%s_val =\n" n n;
4791 pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4792 pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4794 pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4795 pr " return ctx.ret.%s.%s_val;\n" n n
4797 pr " /* caller will free this */\n";
4798 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4799 | RStructList (n, _) ->
4800 pr " /* caller will free this */\n";
4801 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4803 pr " *size_r = ctx.ret.%s.%s_len;\n" n n;
4804 pr " return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4810 (* Functions to free structures. *)
4811 pr "/* Structure-freeing functions. These rely on the fact that the\n";
4812 pr " * structure format is identical to the XDR format. See note in\n";
4813 pr " * generator.ml.\n";
4820 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4822 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4828 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4830 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4837 (* Generate daemon/actions.h. *)
4838 and generate_daemon_actions_h () =
4839 generate_header CStyle GPLv2;
4841 pr "#include \"../src/guestfs_protocol.h\"\n";
4845 fun (name, style, _, _, _, _, _) ->
4847 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4851 (* Generate the server-side stubs. *)
4852 and generate_daemon_actions () =
4853 generate_header CStyle GPLv2;
4855 pr "#include <config.h>\n";
4857 pr "#include <stdio.h>\n";
4858 pr "#include <stdlib.h>\n";
4859 pr "#include <string.h>\n";
4860 pr "#include <inttypes.h>\n";
4861 pr "#include <ctype.h>\n";
4862 pr "#include <rpc/types.h>\n";
4863 pr "#include <rpc/xdr.h>\n";
4865 pr "#include \"daemon.h\"\n";
4866 pr "#include \"../src/guestfs_protocol.h\"\n";
4867 pr "#include \"actions.h\"\n";
4871 fun (name, style, _, _, _, _, _) ->
4872 (* Generate server-side stubs. *)
4873 pr "static void %s_stub (XDR *xdr_in)\n" name;
4876 match fst style with
4877 | RErr | RInt _ -> pr " int r;\n"; "-1"
4878 | RInt64 _ -> pr " int64_t r;\n"; "-1"
4879 | RBool _ -> pr " int r;\n"; "-1"
4880 | RConstString _ | RConstOptString _ ->
4881 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4882 | RString _ -> pr " char *r;\n"; "NULL"
4883 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
4884 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
4885 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
4887 pr " size_t size;\n";
4891 (match snd style with
4894 pr " struct guestfs_%s_args args;\n" name;
4897 | Device n | Dev_or_Path n
4900 | OptString n -> pr " char *%s;\n" n
4901 | StringList n -> pr " char **%s;\n" n
4902 | Bool n -> pr " int %s;\n" n
4903 | Int n -> pr " int %s;\n" n
4904 | FileIn _ | FileOut _ -> ()
4909 (match snd style with
4912 pr " memset (&args, 0, sizeof args);\n";
4914 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4915 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4919 pr " char *%s = args.%s;\n" n n
4925 pr " ABS_PATH (%s, goto done);\n" n;
4928 pr " RESOLVE_DEVICE (%s, goto done);" n;
4931 pr " REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);" n;
4932 | String n -> pr_args n
4933 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
4935 pr " %s = realloc (args.%s.%s_val,\n" n n n;
4936 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4937 pr " if (%s == NULL) {\n" n;
4938 pr " reply_with_perror (\"realloc\");\n";
4941 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
4942 pr " args.%s.%s_val = %s;\n" n n n;
4943 | Bool n -> pr " %s = args.%s;\n" n n
4944 | Int n -> pr " %s = args.%s;\n" n n
4945 | FileIn _ | FileOut _ -> ()
4950 (* this is used at least for do_equal *)
4951 if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
4952 (* Emit NEED_ROOT just once, even when there are two or
4953 more Pathname args *)
4954 pr " NEED_ROOT (goto done);\n";
4957 (* Don't want to call the impl with any FileIn or FileOut
4958 * parameters, since these go "outside" the RPC protocol.
4961 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
4963 pr " r = do_%s " name;
4964 generate_c_call_args (fst style, args');
4967 pr " if (r == %s)\n" error_code;
4968 pr " /* do_%s has already called reply_with_error */\n" name;
4972 (* If there are any FileOut parameters, then the impl must
4973 * send its own reply.
4976 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
4978 pr " /* do_%s has already sent a reply */\n" name
4980 match fst style with
4981 | RErr -> pr " reply (NULL, NULL);\n"
4982 | RInt n | RInt64 n | RBool n ->
4983 pr " struct guestfs_%s_ret ret;\n" name;
4984 pr " ret.%s = r;\n" n;
4985 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4987 | RConstString _ | RConstOptString _ ->
4988 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4990 pr " struct guestfs_%s_ret ret;\n" name;
4991 pr " ret.%s = r;\n" n;
4992 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4995 | RStringList n | RHashtable n ->
4996 pr " struct guestfs_%s_ret ret;\n" name;
4997 pr " ret.%s.%s_len = count_strings (r);\n" n n;
4998 pr " ret.%s.%s_val = r;\n" n n;
4999 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5001 pr " free_strings (r);\n"
5003 pr " struct guestfs_%s_ret ret;\n" name;
5004 pr " ret.%s = *r;\n" n;
5005 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5007 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5009 | RStructList (n, _) ->
5010 pr " struct guestfs_%s_ret ret;\n" name;
5011 pr " ret.%s = *r;\n" n;
5012 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5014 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5017 pr " struct guestfs_%s_ret ret;\n" name;
5018 pr " ret.%s.%s_val = r;\n" n n;
5019 pr " ret.%s.%s_len = size;\n" n n;
5020 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5025 (* Free the args. *)
5026 (match snd style with
5031 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5038 (* Dispatch function. *)
5039 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5041 pr " switch (proc_nr) {\n";
5044 fun (name, style, _, _, _, _, _) ->
5045 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
5046 pr " %s_stub (xdr_in);\n" name;
5051 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";
5056 (* LVM columns and tokenization functions. *)
5057 (* XXX This generates crap code. We should rethink how we
5063 pr "static const char *lvm_%s_cols = \"%s\";\n"
5064 typ (String.concat "," (List.map fst cols));
5067 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5069 pr " char *tok, *p, *next;\n";
5073 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5076 pr " if (!str) {\n";
5077 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5080 pr " if (!*str || isspace (*str)) {\n";
5081 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5086 fun (name, coltype) ->
5087 pr " if (!tok) {\n";
5088 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5091 pr " p = strchrnul (tok, ',');\n";
5092 pr " if (*p) next = p+1; else next = NULL;\n";
5093 pr " *p = '\\0';\n";
5096 pr " r->%s = strdup (tok);\n" name;
5097 pr " if (r->%s == NULL) {\n" name;
5098 pr " perror (\"strdup\");\n";
5102 pr " for (i = j = 0; i < 32; ++j) {\n";
5103 pr " if (tok[j] == '\\0') {\n";
5104 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5106 pr " } else if (tok[j] != '-')\n";
5107 pr " r->%s[i++] = tok[j];\n" name;
5110 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5111 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5115 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5116 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5120 pr " if (tok[0] == '\\0')\n";
5121 pr " r->%s = -1;\n" name;
5122 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5123 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5126 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5127 assert false (* can never be an LVM column *)
5129 pr " tok = next;\n";
5132 pr " if (tok != NULL) {\n";
5133 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5140 pr "guestfs_int_lvm_%s_list *\n" typ;
5141 pr "parse_command_line_%ss (void)\n" typ;
5143 pr " char *out, *err;\n";
5144 pr " char *p, *pend;\n";
5146 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
5147 pr " void *newp;\n";
5149 pr " ret = malloc (sizeof *ret);\n";
5150 pr " if (!ret) {\n";
5151 pr " reply_with_perror (\"malloc\");\n";
5152 pr " return NULL;\n";
5155 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5156 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5158 pr " r = command (&out, &err,\n";
5159 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
5160 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5161 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5162 pr " if (r == -1) {\n";
5163 pr " reply_with_error (\"%%s\", err);\n";
5164 pr " free (out);\n";
5165 pr " free (err);\n";
5166 pr " free (ret);\n";
5167 pr " return NULL;\n";
5170 pr " free (err);\n";
5172 pr " /* Tokenize each line of the output. */\n";
5175 pr " while (p) {\n";
5176 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
5177 pr " if (pend) {\n";
5178 pr " *pend = '\\0';\n";
5182 pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
5185 pr " if (!*p) { /* Empty line? Skip it. */\n";
5190 pr " /* Allocate some space to store this next entry. */\n";
5191 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5192 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5193 pr " if (newp == NULL) {\n";
5194 pr " reply_with_perror (\"realloc\");\n";
5195 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5196 pr " free (ret);\n";
5197 pr " free (out);\n";
5198 pr " return NULL;\n";
5200 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5202 pr " /* Tokenize the next entry. */\n";
5203 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5204 pr " if (r == -1) {\n";
5205 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5206 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5207 pr " free (ret);\n";
5208 pr " free (out);\n";
5209 pr " return NULL;\n";
5216 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5218 pr " free (out);\n";
5219 pr " return ret;\n";
5222 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5224 (* Generate a list of function names, for debugging in the daemon.. *)
5225 and generate_daemon_names () =
5226 generate_header CStyle GPLv2;
5228 pr "#include <config.h>\n";
5230 pr "#include \"daemon.h\"\n";
5233 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5234 pr "const char *function_names[] = {\n";
5236 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5240 (* Generate the tests. *)
5241 and generate_tests () =
5242 generate_header CStyle GPLv2;
5249 #include <sys/types.h>
5252 #include \"guestfs.h\"
5254 static guestfs_h *g;
5255 static int suppress_error = 0;
5257 static void print_error (guestfs_h *g, void *data, const char *msg)
5259 if (!suppress_error)
5260 fprintf (stderr, \"%%s\\n\", msg);
5263 static void print_strings (char * const * const argv)
5267 for (argc = 0; argv[argc] != NULL; ++argc)
5268 printf (\"\\t%%s\\n\", argv[argc]);
5272 static void print_table (char * const * const argv)
5276 for (i = 0; argv[i] != NULL; i += 2)
5277 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5283 (* Generate a list of commands which are not tested anywhere. *)
5284 pr "static void no_test_warnings (void)\n";
5287 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5289 fun (_, _, _, _, tests, _, _) ->
5290 let tests = filter_map (
5292 | (_, (Always|If _|Unless _), test) -> Some test
5293 | (_, Disabled, _) -> None
5295 let seq = List.concat (List.map seq_of_test tests) in
5296 let cmds_tested = List.map List.hd seq in
5297 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5301 fun (name, _, _, _, _, _, _) ->
5302 if not (Hashtbl.mem hash name) then
5303 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5309 (* Generate the actual tests. Note that we generate the tests
5310 * in reverse order, deliberately, so that (in general) the
5311 * newest tests run first. This makes it quicker and easier to
5316 fun (name, _, _, _, tests, _, _) ->
5317 mapi (generate_one_test name) tests
5318 ) (List.rev all_functions) in
5319 let test_names = List.concat test_names in
5320 let nr_tests = List.length test_names in
5323 int main (int argc, char *argv[])
5327 const char *filename;
5329 int nr_tests, test_num = 0;
5331 setbuf (stdout, NULL);
5333 no_test_warnings ();
5335 g = guestfs_create ();
5337 printf (\"guestfs_create FAILED\\n\");
5341 guestfs_set_error_handler (g, print_error, NULL);
5343 guestfs_set_path (g, \"../appliance\");
5345 filename = \"test1.img\";
5346 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5351 if (lseek (fd, %d, SEEK_SET) == -1) {
5357 if (write (fd, &c, 1) == -1) {
5363 if (close (fd) == -1) {
5368 if (guestfs_add_drive (g, filename) == -1) {
5369 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5373 filename = \"test2.img\";
5374 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5379 if (lseek (fd, %d, SEEK_SET) == -1) {
5385 if (write (fd, &c, 1) == -1) {
5391 if (close (fd) == -1) {
5396 if (guestfs_add_drive (g, filename) == -1) {
5397 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5401 filename = \"test3.img\";
5402 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5407 if (lseek (fd, %d, SEEK_SET) == -1) {
5413 if (write (fd, &c, 1) == -1) {
5419 if (close (fd) == -1) {
5424 if (guestfs_add_drive (g, filename) == -1) {
5425 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5429 if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
5430 printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
5434 if (guestfs_launch (g) == -1) {
5435 printf (\"guestfs_launch FAILED\\n\");
5439 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5442 if (guestfs_wait_ready (g) == -1) {
5443 printf (\"guestfs_wait_ready FAILED\\n\");
5447 /* Cancel previous alarm. */
5452 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5456 pr " test_num++;\n";
5457 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5458 pr " if (%s () == -1) {\n" test_name;
5459 pr " printf (\"%s FAILED\\n\");\n" test_name;
5465 pr " guestfs_close (g);\n";
5466 pr " unlink (\"test1.img\");\n";
5467 pr " unlink (\"test2.img\");\n";
5468 pr " unlink (\"test3.img\");\n";
5471 pr " if (failed > 0) {\n";
5472 pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
5480 and generate_one_test name i (init, prereq, test) =
5481 let test_name = sprintf "test_%s_%d" name i in
5484 static int %s_skip (void)
5488 str = getenv (\"TEST_ONLY\");
5490 return strstr (str, \"%s\") == NULL;
5491 str = getenv (\"SKIP_%s\");
5492 if (str && strcmp (str, \"1\") == 0) return 1;
5493 str = getenv (\"SKIP_TEST_%s\");
5494 if (str && strcmp (str, \"1\") == 0) return 1;
5498 " test_name name (String.uppercase test_name) (String.uppercase name);
5501 | Disabled | Always -> ()
5502 | If code | Unless code ->
5503 pr "static int %s_prereq (void)\n" test_name;
5511 static int %s (void)
5514 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5518 " test_name test_name test_name;
5522 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5524 pr " if (! %s_prereq ()) {\n" test_name;
5525 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5529 generate_one_test_body name i test_name init test;
5531 pr " if (%s_prereq ()) {\n" test_name;
5532 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5536 generate_one_test_body name i test_name init test;
5538 generate_one_test_body name i test_name init test
5546 and generate_one_test_body name i test_name init test =
5548 | InitNone (* XXX at some point, InitNone and InitEmpty became
5549 * folded together as the same thing. Really we should
5550 * make InitNone do nothing at all, but the tests may
5551 * need to be checked to make sure this is OK.
5554 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5555 List.iter (generate_test_command_call test_name)
5556 [["blockdev_setrw"; "/dev/sda"];
5560 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5561 List.iter (generate_test_command_call test_name)
5562 [["blockdev_setrw"; "/dev/sda"];
5565 ["sfdiskM"; "/dev/sda"; ","]]
5567 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5568 List.iter (generate_test_command_call test_name)
5569 [["blockdev_setrw"; "/dev/sda"];
5572 ["sfdiskM"; "/dev/sda"; ","];
5573 ["mkfs"; "ext2"; "/dev/sda1"];
5574 ["mount"; "/dev/sda1"; "/"]]
5575 | InitBasicFSonLVM ->
5576 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5578 List.iter (generate_test_command_call test_name)
5579 [["blockdev_setrw"; "/dev/sda"];
5582 ["sfdiskM"; "/dev/sda"; ","];
5583 ["pvcreate"; "/dev/sda1"];
5584 ["vgcreate"; "VG"; "/dev/sda1"];
5585 ["lvcreate"; "LV"; "VG"; "8"];
5586 ["mkfs"; "ext2"; "/dev/VG/LV"];
5587 ["mount"; "/dev/VG/LV"; "/"]]
5589 pr " /* InitSquashFS for %s */\n" test_name;
5590 List.iter (generate_test_command_call test_name)
5591 [["blockdev_setrw"; "/dev/sda"];
5594 ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
5597 let get_seq_last = function
5599 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5602 let seq = List.rev seq in
5603 List.rev (List.tl seq), List.hd seq
5608 pr " /* TestRun for %s (%d) */\n" name i;
5609 List.iter (generate_test_command_call test_name) seq
5610 | TestOutput (seq, expected) ->
5611 pr " /* TestOutput for %s (%d) */\n" name i;
5612 pr " const char *expected = \"%s\";\n" (c_quote expected);
5613 let seq, last = get_seq_last seq in
5615 pr " if (strcmp (r, expected) != 0) {\n";
5616 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5620 List.iter (generate_test_command_call test_name) seq;
5621 generate_test_command_call ~test test_name last
5622 | TestOutputList (seq, expected) ->
5623 pr " /* TestOutputList for %s (%d) */\n" name i;
5624 let seq, last = get_seq_last seq in
5628 pr " if (!r[%d]) {\n" i;
5629 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5630 pr " print_strings (r);\n";
5634 pr " const char *expected = \"%s\";\n" (c_quote str);
5635 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5636 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5641 pr " if (r[%d] != NULL) {\n" (List.length expected);
5642 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5644 pr " print_strings (r);\n";
5648 List.iter (generate_test_command_call test_name) seq;
5649 generate_test_command_call ~test test_name last
5650 | TestOutputListOfDevices (seq, expected) ->
5651 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
5652 let seq, last = get_seq_last seq in
5656 pr " if (!r[%d]) {\n" i;
5657 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5658 pr " print_strings (r);\n";
5662 pr " const char *expected = \"%s\";\n" (c_quote str);
5663 pr " r[%d][5] = 's';\n" i;
5664 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5665 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5670 pr " if (r[%d] != NULL) {\n" (List.length expected);
5671 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5673 pr " print_strings (r);\n";
5677 List.iter (generate_test_command_call test_name) seq;
5678 generate_test_command_call ~test test_name last
5679 | TestOutputInt (seq, expected) ->
5680 pr " /* TestOutputInt for %s (%d) */\n" name i;
5681 let seq, last = get_seq_last seq in
5683 pr " if (r != %d) {\n" expected;
5684 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5690 List.iter (generate_test_command_call test_name) seq;
5691 generate_test_command_call ~test test_name last
5692 | TestOutputIntOp (seq, op, expected) ->
5693 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
5694 let seq, last = get_seq_last seq in
5696 pr " if (! (r %s %d)) {\n" op expected;
5697 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5698 test_name op expected;
5703 List.iter (generate_test_command_call test_name) seq;
5704 generate_test_command_call ~test test_name last
5705 | TestOutputTrue seq ->
5706 pr " /* TestOutputTrue for %s (%d) */\n" name i;
5707 let seq, last = get_seq_last seq in
5710 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5715 List.iter (generate_test_command_call test_name) seq;
5716 generate_test_command_call ~test test_name last
5717 | TestOutputFalse seq ->
5718 pr " /* TestOutputFalse for %s (%d) */\n" name i;
5719 let seq, last = get_seq_last seq in
5722 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5727 List.iter (generate_test_command_call test_name) seq;
5728 generate_test_command_call ~test test_name last
5729 | TestOutputLength (seq, expected) ->
5730 pr " /* TestOutputLength for %s (%d) */\n" name i;
5731 let seq, last = get_seq_last seq in
5734 pr " for (j = 0; j < %d; ++j)\n" expected;
5735 pr " if (r[j] == NULL) {\n";
5736 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
5738 pr " print_strings (r);\n";
5741 pr " if (r[j] != NULL) {\n";
5742 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
5744 pr " print_strings (r);\n";
5748 List.iter (generate_test_command_call test_name) seq;
5749 generate_test_command_call ~test test_name last
5750 | TestOutputBuffer (seq, expected) ->
5751 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
5752 pr " const char *expected = \"%s\";\n" (c_quote expected);
5753 let seq, last = get_seq_last seq in
5754 let len = String.length expected in
5756 pr " if (size != %d) {\n" len;
5757 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5760 pr " if (strncmp (r, expected, size) != 0) {\n";
5761 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5765 List.iter (generate_test_command_call test_name) seq;
5766 generate_test_command_call ~test test_name last
5767 | TestOutputStruct (seq, checks) ->
5768 pr " /* TestOutputStruct for %s (%d) */\n" name i;
5769 let seq, last = get_seq_last seq in
5773 | CompareWithInt (field, expected) ->
5774 pr " if (r->%s != %d) {\n" field expected;
5775 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5776 test_name field expected;
5777 pr " (int) r->%s);\n" field;
5780 | CompareWithIntOp (field, op, expected) ->
5781 pr " if (!(r->%s %s %d)) {\n" field op expected;
5782 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5783 test_name field op expected;
5784 pr " (int) r->%s);\n" field;
5787 | CompareWithString (field, expected) ->
5788 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5789 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5790 test_name field expected;
5791 pr " r->%s);\n" field;
5794 | CompareFieldsIntEq (field1, field2) ->
5795 pr " if (r->%s != r->%s) {\n" field1 field2;
5796 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5797 test_name field1 field2;
5798 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
5801 | CompareFieldsStrEq (field1, field2) ->
5802 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5803 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5804 test_name field1 field2;
5805 pr " r->%s, r->%s);\n" field1 field2;
5810 List.iter (generate_test_command_call test_name) seq;
5811 generate_test_command_call ~test test_name last
5812 | TestLastFail seq ->
5813 pr " /* TestLastFail for %s (%d) */\n" name i;
5814 let seq, last = get_seq_last seq in
5815 List.iter (generate_test_command_call test_name) seq;
5816 generate_test_command_call test_name ~expect_error:true last
5818 (* Generate the code to run a command, leaving the result in 'r'.
5819 * If you expect to get an error then you should set expect_error:true.
5821 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5823 | [] -> assert false
5825 (* Look up the command to find out what args/ret it has. *)
5828 let _, style, _, _, _, _, _ =
5829 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5832 failwithf "%s: in test, command %s was not found" test_name name in
5834 if List.length (snd style) <> List.length args then
5835 failwithf "%s: in test, wrong number of args given to %s"
5842 | OptString n, "NULL" -> ()
5845 | Dev_or_Path n, arg
5847 | OptString n, arg ->
5848 pr " const char *%s = \"%s\";\n" n (c_quote arg);
5851 | FileIn _, _ | FileOut _, _ -> ()
5852 | StringList n, arg ->
5853 let strs = string_split " " arg in
5856 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
5858 pr " const char *%s[] = {\n" n;
5860 fun i _ -> pr " %s_%d,\n" n i
5864 ) (List.combine (snd style) args);
5867 match fst style with
5868 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
5869 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5870 | RConstString _ | RConstOptString _ ->
5871 pr " const char *r;\n"; "NULL"
5872 | RString _ -> pr " char *r;\n"; "NULL"
5873 | RStringList _ | RHashtable _ ->
5877 | RStruct (_, typ) ->
5878 pr " struct guestfs_%s *r;\n" typ; "NULL"
5879 | RStructList (_, typ) ->
5880 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
5883 pr " size_t size;\n";
5886 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
5887 pr " r = guestfs_%s (g" name;
5889 (* Generate the parameters. *)
5892 | OptString _, "NULL" -> pr ", NULL"
5894 | Device n, _ | Dev_or_Path n, _
5898 | FileIn _, arg | FileOut _, arg ->
5899 pr ", \"%s\"" (c_quote arg)
5900 | StringList n, _ ->
5904 try int_of_string arg
5905 with Failure "int_of_string" ->
5906 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5909 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5910 ) (List.combine (snd style) args);
5912 (match fst style with
5913 | RBufferOut _ -> pr ", &size"
5919 if not expect_error then
5920 pr " if (r == %s)\n" error_code
5922 pr " if (r != %s)\n" error_code;
5925 (* Insert the test code. *)
5931 (match fst style with
5932 | RErr | RInt _ | RInt64 _ | RBool _
5933 | RConstString _ | RConstOptString _ -> ()
5934 | RString _ | RBufferOut _ -> pr " free (r);\n"
5935 | RStringList _ | RHashtable _ ->
5936 pr " for (i = 0; r[i] != NULL; ++i)\n";
5937 pr " free (r[i]);\n";
5939 | RStruct (_, typ) ->
5940 pr " guestfs_free_%s (r);\n" typ
5941 | RStructList (_, typ) ->
5942 pr " guestfs_free_%s_list (r);\n" typ
5948 let str = replace_str str "\r" "\\r" in
5949 let str = replace_str str "\n" "\\n" in
5950 let str = replace_str str "\t" "\\t" in
5951 let str = replace_str str "\000" "\\0" in
5954 (* Generate a lot of different functions for guestfish. *)
5955 and generate_fish_cmds () =
5956 generate_header CStyle GPLv2;
5960 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5962 let all_functions_sorted =
5964 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5965 ) all_functions_sorted in
5967 pr "#include <stdio.h>\n";
5968 pr "#include <stdlib.h>\n";
5969 pr "#include <string.h>\n";
5970 pr "#include <inttypes.h>\n";
5971 pr "#include <ctype.h>\n";
5973 pr "#include <guestfs.h>\n";
5974 pr "#include \"fish.h\"\n";
5977 (* list_commands function, which implements guestfish -h *)
5978 pr "void list_commands (void)\n";
5980 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
5981 pr " list_builtin_commands ();\n";
5983 fun (name, _, _, flags, _, shortdesc, _) ->
5984 let name = replace_char name '_' '-' in
5985 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
5987 ) all_functions_sorted;
5988 pr " printf (\" %%s\\n\",";
5989 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
5993 (* display_command function, which implements guestfish -h cmd *)
5994 pr "void display_command (const char *cmd)\n";
5997 fun (name, style, _, flags, _, shortdesc, longdesc) ->
5998 let name2 = replace_char name '_' '-' in
6000 try find_map (function FishAlias n -> Some n | _ -> None) flags
6001 with Not_found -> name in
6002 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6004 match snd style with
6008 name2 (String.concat "> <" (List.map name_of_argt args)) in
6011 if List.mem ProtocolLimitWarning flags then
6012 ("\n\n" ^ protocol_limit_warning)
6015 (* For DangerWillRobinson commands, we should probably have
6016 * guestfish prompt before allowing you to use them (especially
6017 * in interactive mode). XXX
6021 if List.mem DangerWillRobinson flags then
6022 ("\n\n" ^ danger_will_robinson)
6027 match deprecation_notice flags with
6029 | Some txt -> "\n\n" ^ txt in
6031 let describe_alias =
6032 if name <> alias then
6033 sprintf "\n\nYou can use '%s' as an alias for this command." alias
6037 pr "strcasecmp (cmd, \"%s\") == 0" name;
6038 if name <> name2 then
6039 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6040 if name <> alias then
6041 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6043 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
6045 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6048 pr " display_builtin_command (cmd);\n";
6052 (* print_* functions *)
6056 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6058 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6067 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6069 pr " printf (\"%s: \");\n" name;
6070 pr " for (i = 0; i < 32; ++i)\n";
6071 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6072 pr " printf (\"\\n\");\n"
6074 pr " printf (\"%%s%s: \", indent);\n" name;
6075 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6076 pr " if (isprint (%s->%s[i]))\n" typ name;
6077 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6079 pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6080 pr " printf (\"\\n\");\n"
6081 | name, (FUInt64|FBytes) ->
6082 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6085 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6088 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6091 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6094 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6096 | name, FOptPercent ->
6097 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6098 typ name name typ name;
6099 pr " else printf (\"%%s%s: \\n\", indent);\n" name
6103 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6105 pr " print_%s_indent (%s, \"\");\n" typ typ;
6108 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6113 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6114 pr " printf (\"[%%d] = {\\n\", i);\n";
6115 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
6116 pr " printf (\"}\\n\");\n";
6122 (* run_<action> actions *)
6124 fun (name, style, _, flags, _, _, _) ->
6125 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6127 (match fst style with
6130 | RBool _ -> pr " int r;\n"
6131 | RInt64 _ -> pr " int64_t r;\n"
6132 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
6133 | RString _ -> pr " char *r;\n"
6134 | RStringList _ | RHashtable _ -> pr " char **r;\n"
6135 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
6136 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
6139 pr " size_t size;\n";
6144 | Device n | Dev_or_Path n
6148 | FileOut n -> pr " const char *%s;\n" n
6149 | StringList n -> pr " char **%s;\n" n
6150 | Bool n -> pr " int %s;\n" n
6151 | Int n -> pr " int %s;\n" n
6154 (* Check and convert parameters. *)
6155 let argc_expected = List.length (snd style) in
6156 pr " if (argc != %d) {\n" argc_expected;
6157 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6159 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6166 | Device name | Dev_or_Path name | String name -> pr " %s = argv[%d];\n" name i
6168 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6171 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6174 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6176 | StringList name ->
6177 pr " %s = parse_string_list (argv[%d]);\n" name i
6179 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6181 pr " %s = atoi (argv[%d]);\n" name i
6184 (* Call C API function. *)
6186 try find_map (function FishAction n -> Some n | _ -> None) flags
6187 with Not_found -> sprintf "guestfs_%s" name in
6189 generate_c_call_args ~handle:"g" style;
6192 (* Check return value for errors and display command results. *)
6193 (match fst style with
6194 | RErr -> pr " return r;\n"
6196 pr " if (r == -1) return -1;\n";
6197 pr " printf (\"%%d\\n\", r);\n";
6200 pr " if (r == -1) return -1;\n";
6201 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6204 pr " if (r == -1) return -1;\n";
6205 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6208 pr " if (r == NULL) return -1;\n";
6209 pr " printf (\"%%s\\n\", r);\n";
6211 | RConstOptString _ ->
6212 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6215 pr " if (r == NULL) return -1;\n";
6216 pr " printf (\"%%s\\n\", r);\n";
6220 pr " if (r == NULL) return -1;\n";
6221 pr " print_strings (r);\n";
6222 pr " free_strings (r);\n";
6224 | RStruct (_, typ) ->
6225 pr " if (r == NULL) return -1;\n";
6226 pr " print_%s (r);\n" typ;
6227 pr " guestfs_free_%s (r);\n" typ;
6229 | RStructList (_, typ) ->
6230 pr " if (r == NULL) return -1;\n";
6231 pr " print_%s_list (r);\n" typ;
6232 pr " guestfs_free_%s_list (r);\n" typ;
6235 pr " if (r == NULL) return -1;\n";
6236 pr " print_table (r);\n";
6237 pr " free_strings (r);\n";
6240 pr " if (r == NULL) return -1;\n";
6241 pr " fwrite (r, size, 1, stdout);\n";
6249 (* run_action function *)
6250 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6253 fun (name, _, _, flags, _, _, _) ->
6254 let name2 = replace_char name '_' '-' in
6256 try find_map (function FishAlias n -> Some n | _ -> None) flags
6257 with Not_found -> name in
6259 pr "strcasecmp (cmd, \"%s\") == 0" name;
6260 if name <> name2 then
6261 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6262 if name <> alias then
6263 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6265 pr " return run_%s (cmd, argc, argv);\n" name;
6269 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6276 (* Readline completion for guestfish. *)
6277 and generate_fish_completion () =
6278 generate_header CStyle GPLv2;
6282 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6292 #ifdef HAVE_LIBREADLINE
6293 #include <readline/readline.h>
6298 #ifdef HAVE_LIBREADLINE
6300 static const char *const commands[] = {
6301 BUILTIN_COMMANDS_FOR_COMPLETION,
6304 (* Get the commands, including the aliases. They don't need to be
6305 * sorted - the generator() function just does a dumb linear search.
6309 fun (name, _, _, flags, _, _, _) ->
6310 let name2 = replace_char name '_' '-' in
6312 try find_map (function FishAlias n -> Some n | _ -> None) flags
6313 with Not_found -> name in
6315 if name <> alias then [name2; alias] else [name2]
6317 let commands = List.flatten commands in
6319 List.iter (pr " \"%s\",\n") commands;
6325 generator (const char *text, int state)
6327 static int index, len;
6332 len = strlen (text);
6335 rl_attempted_completion_over = 1;
6337 while ((name = commands[index]) != NULL) {
6339 if (strncasecmp (name, text, len) == 0)
6340 return strdup (name);
6346 #endif /* HAVE_LIBREADLINE */
6348 char **do_completion (const char *text, int start, int end)
6350 char **matches = NULL;
6352 #ifdef HAVE_LIBREADLINE
6353 rl_completion_append_character = ' ';
6356 matches = rl_completion_matches (text, generator);
6357 else if (complete_dest_paths)
6358 matches = rl_completion_matches (text, complete_dest_paths_generator);
6365 (* Generate the POD documentation for guestfish. *)
6366 and generate_fish_actions_pod () =
6367 let all_functions_sorted =
6369 fun (_, _, _, flags, _, _, _) ->
6370 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6371 ) all_functions_sorted in
6373 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6376 fun (name, style, _, flags, _, _, longdesc) ->
6378 Str.global_substitute rex (
6381 try Str.matched_group 1 s
6383 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6384 "C<" ^ replace_char sub '_' '-' ^ ">"
6386 let name = replace_char name '_' '-' in
6388 try find_map (function FishAlias n -> Some n | _ -> None) flags
6389 with Not_found -> name in
6391 pr "=head2 %s" name;
6392 if name <> alias then
6399 | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6400 | OptString n -> pr " %s" n
6401 | StringList n -> pr " '%s ...'" n
6402 | Bool _ -> pr " true|false"
6403 | Int n -> pr " %s" n
6404 | FileIn n | FileOut n -> pr " (%s|-)" n
6408 pr "%s\n\n" longdesc;
6410 if List.exists (function FileIn _ | FileOut _ -> true
6411 | _ -> false) (snd style) then
6412 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6414 if List.mem ProtocolLimitWarning flags then
6415 pr "%s\n\n" protocol_limit_warning;
6417 if List.mem DangerWillRobinson flags then
6418 pr "%s\n\n" danger_will_robinson;
6420 match deprecation_notice flags with
6422 | Some txt -> pr "%s\n\n" txt
6423 ) all_functions_sorted
6425 (* Generate a C function prototype. *)
6426 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6427 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6429 ?handle name style =
6430 if extern then pr "extern ";
6431 if static then pr "static ";
6432 (match fst style with
6434 | RInt _ -> pr "int "
6435 | RInt64 _ -> pr "int64_t "
6436 | RBool _ -> pr "int "
6437 | RConstString _ | RConstOptString _ -> pr "const char *"
6438 | RString _ | RBufferOut _ -> pr "char *"
6439 | RStringList _ | RHashtable _ -> pr "char **"
6440 | RStruct (_, typ) ->
6441 if not in_daemon then pr "struct guestfs_%s *" typ
6442 else pr "guestfs_int_%s *" typ
6443 | RStructList (_, typ) ->
6444 if not in_daemon then pr "struct guestfs_%s_list *" typ
6445 else pr "guestfs_int_%s_list *" typ
6447 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6448 pr "%s%s (" prefix name;
6449 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6452 let comma = ref false in
6455 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6459 if single_line then pr ", " else pr ",\n\t\t"
6466 | Device n | Dev_or_Path n
6470 pr "const char *%s" n
6473 if not in_daemon then pr "char * const* const %s" n
6474 else pr "char **%s" n
6475 | Bool n -> next (); pr "int %s" n
6476 | Int n -> next (); pr "int %s" n
6479 if not in_daemon then (next (); pr "const char *%s" n)
6481 if is_RBufferOut then (next (); pr "size_t *size_r");
6484 if semicolon then pr ";";
6485 if newline then pr "\n"
6487 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6488 and generate_c_call_args ?handle ?(decl = false) style =
6490 let comma = ref false in
6492 if !comma then pr ", ";
6497 | Some handle -> pr "%s" handle; comma := true
6502 pr "%s" (name_of_argt arg)
6504 (* For RBufferOut calls, add implicit &size parameter. *)
6506 match fst style with
6514 (* Generate the OCaml bindings interface. *)
6515 and generate_ocaml_mli () =
6516 generate_header OCamlStyle LGPLv2;
6519 (** For API documentation you should refer to the C API
6520 in the guestfs(3) manual page. The OCaml API uses almost
6521 exactly the same calls. *)
6524 (** A [guestfs_h] handle. *)
6526 exception Error of string
6527 (** This exception is raised when there is an error. *)
6529 val create : unit -> t
6531 val close : t -> unit
6532 (** Handles are closed by the garbage collector when they become
6533 unreferenced, but callers can also call this in order to
6534 provide predictable cleanup. *)
6537 generate_ocaml_structure_decls ();
6541 fun (name, style, _, _, _, shortdesc, _) ->
6542 generate_ocaml_prototype name style;
6543 pr "(** %s *)\n" shortdesc;
6547 (* Generate the OCaml bindings implementation. *)
6548 and generate_ocaml_ml () =
6549 generate_header OCamlStyle LGPLv2;
6553 exception Error of string
6554 external create : unit -> t = \"ocaml_guestfs_create\"
6555 external close : t -> unit = \"ocaml_guestfs_close\"
6558 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6562 generate_ocaml_structure_decls ();
6566 fun (name, style, _, _, _, shortdesc, _) ->
6567 generate_ocaml_prototype ~is_external:true name style;
6570 (* Generate the OCaml bindings C implementation. *)
6571 and generate_ocaml_c () =
6572 generate_header CStyle LGPLv2;
6579 #include <caml/config.h>
6580 #include <caml/alloc.h>
6581 #include <caml/callback.h>
6582 #include <caml/fail.h>
6583 #include <caml/memory.h>
6584 #include <caml/mlvalues.h>
6585 #include <caml/signals.h>
6587 #include <guestfs.h>
6589 #include \"guestfs_c.h\"
6591 /* Copy a hashtable of string pairs into an assoc-list. We return
6592 * the list in reverse order, but hashtables aren't supposed to be
6595 static CAMLprim value
6596 copy_table (char * const * argv)
6599 CAMLlocal5 (rv, pairv, kv, vv, cons);
6603 for (i = 0; argv[i] != NULL; i += 2) {
6604 kv = caml_copy_string (argv[i]);
6605 vv = caml_copy_string (argv[i+1]);
6606 pairv = caml_alloc (2, 0);
6607 Store_field (pairv, 0, kv);
6608 Store_field (pairv, 1, vv);
6609 cons = caml_alloc (2, 0);
6610 Store_field (cons, 1, rv);
6612 Store_field (cons, 0, pairv);
6620 (* Struct copy functions. *)
6623 let has_optpercent_col =
6624 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6626 pr "static CAMLprim value\n";
6627 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6629 pr " CAMLparam0 ();\n";
6630 if has_optpercent_col then
6631 pr " CAMLlocal3 (rv, v, v2);\n"
6633 pr " CAMLlocal2 (rv, v);\n";
6635 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
6640 pr " v = caml_copy_string (%s->%s);\n" typ name
6642 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
6643 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6646 pr " v = caml_alloc_string (32);\n";
6647 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
6648 | name, (FBytes|FInt64|FUInt64) ->
6649 pr " v = caml_copy_int64 (%s->%s);\n" typ name
6650 | name, (FInt32|FUInt32) ->
6651 pr " v = caml_copy_int32 (%s->%s);\n" typ name
6652 | name, FOptPercent ->
6653 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6654 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
6655 pr " v = caml_alloc (1, 0);\n";
6656 pr " Store_field (v, 0, v2);\n";
6657 pr " } else /* None */\n";
6658 pr " v = Val_int (0);\n";
6660 pr " v = Val_int (%s->%s);\n" typ name
6662 pr " Store_field (rv, %d, v);\n" i
6664 pr " CAMLreturn (rv);\n";
6668 pr "static CAMLprim value\n";
6669 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
6672 pr " CAMLparam0 ();\n";
6673 pr " CAMLlocal2 (rv, v);\n";
6676 pr " if (%ss->len == 0)\n" typ;
6677 pr " CAMLreturn (Atom (0));\n";
6679 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
6680 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6681 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
6682 pr " caml_modify (&Field (rv, i), v);\n";
6684 pr " CAMLreturn (rv);\n";
6692 fun (name, style, _, _, _, _, _) ->
6694 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6696 let needs_extra_vs =
6697 match fst style with RConstOptString _ -> true | _ -> false in
6699 pr "CAMLprim value\n";
6700 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6701 List.iter (pr ", value %s") (List.tl params);
6706 | [p1; p2; p3; p4; p5] ->
6707 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
6708 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6709 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6710 pr " CAMLxparam%d (%s);\n"
6711 (List.length rest) (String.concat ", " rest)
6713 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6715 if not needs_extra_vs then
6716 pr " CAMLlocal1 (rv);\n"
6718 pr " CAMLlocal3 (rv, v, v2);\n";
6721 pr " guestfs_h *g = Guestfs_val (gv);\n";
6722 pr " if (g == NULL)\n";
6723 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
6729 | Device n | Dev_or_Path n
6733 pr " const char *%s = String_val (%sv);\n" n n
6735 pr " const char *%s =\n" n;
6736 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6739 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6741 pr " int %s = Bool_val (%sv);\n" n n
6743 pr " int %s = Int_val (%sv);\n" n n
6746 match fst style with
6747 | RErr -> pr " int r;\n"; "-1"
6748 | RInt _ -> pr " int r;\n"; "-1"
6749 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6750 | RBool _ -> pr " int r;\n"; "-1"
6751 | RConstString _ | RConstOptString _ ->
6752 pr " const char *r;\n"; "NULL"
6753 | RString _ -> pr " char *r;\n"; "NULL"
6758 | RStruct (_, typ) ->
6759 pr " struct guestfs_%s *r;\n" typ; "NULL"
6760 | RStructList (_, typ) ->
6761 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6768 pr " size_t size;\n";
6772 pr " caml_enter_blocking_section ();\n";
6773 pr " r = guestfs_%s " name;
6774 generate_c_call_args ~handle:"g" style;
6776 pr " caml_leave_blocking_section ();\n";
6781 pr " ocaml_guestfs_free_strings (%s);\n" n;
6782 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6783 | FileIn _ | FileOut _ -> ()
6786 pr " if (r == %s)\n" error_code;
6787 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6790 (match fst style with
6791 | RErr -> pr " rv = Val_unit;\n"
6792 | RInt _ -> pr " rv = Val_int (r);\n"
6794 pr " rv = caml_copy_int64 (r);\n"
6795 | RBool _ -> pr " rv = Val_bool (r);\n"
6797 pr " rv = caml_copy_string (r);\n"
6798 | RConstOptString _ ->
6799 pr " if (r) { /* Some string */\n";
6800 pr " v = caml_alloc (1, 0);\n";
6801 pr " v2 = caml_copy_string (r);\n";
6802 pr " Store_field (v, 0, v2);\n";
6803 pr " } else /* None */\n";
6804 pr " v = Val_int (0);\n";
6806 pr " rv = caml_copy_string (r);\n";
6809 pr " rv = caml_copy_string_array ((const char **) r);\n";
6810 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6812 | RStruct (_, typ) ->
6813 pr " rv = copy_%s (r);\n" typ;
6814 pr " guestfs_free_%s (r);\n" typ;
6815 | RStructList (_, typ) ->
6816 pr " rv = copy_%s_list (r);\n" typ;
6817 pr " guestfs_free_%s_list (r);\n" typ;
6819 pr " rv = copy_table (r);\n";
6820 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6823 pr " rv = caml_alloc_string (size);\n";
6824 pr " memcpy (String_val (rv), r, size);\n";
6827 pr " CAMLreturn (rv);\n";
6831 if List.length params > 5 then (
6832 pr "CAMLprim value\n";
6833 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6835 pr " return ocaml_guestfs_%s (argv[0]" name;
6836 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6843 and generate_ocaml_structure_decls () =
6846 pr "type %s = {\n" typ;
6849 | name, FString -> pr " %s : string;\n" name
6850 | name, FBuffer -> pr " %s : string;\n" name
6851 | name, FUUID -> pr " %s : string;\n" name
6852 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
6853 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
6854 | name, FChar -> pr " %s : char;\n" name
6855 | name, FOptPercent -> pr " %s : float option;\n" name
6861 and generate_ocaml_prototype ?(is_external = false) name style =
6862 if is_external then pr "external " else pr "val ";
6863 pr "%s : t -> " name;
6866 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6867 | OptString _ -> pr "string option -> "
6868 | StringList _ -> pr "string array -> "
6869 | Bool _ -> pr "bool -> "
6870 | Int _ -> pr "int -> "
6872 (match fst style with
6873 | RErr -> pr "unit" (* all errors are turned into exceptions *)
6874 | RInt _ -> pr "int"
6875 | RInt64 _ -> pr "int64"
6876 | RBool _ -> pr "bool"
6877 | RConstString _ -> pr "string"
6878 | RConstOptString _ -> pr "string option"
6879 | RString _ | RBufferOut _ -> pr "string"
6880 | RStringList _ -> pr "string array"
6881 | RStruct (_, typ) -> pr "%s" typ
6882 | RStructList (_, typ) -> pr "%s array" typ
6883 | RHashtable _ -> pr "(string * string) list"
6885 if is_external then (
6887 if List.length (snd style) + 1 > 5 then
6888 pr "\"ocaml_guestfs_%s_byte\" " name;
6889 pr "\"ocaml_guestfs_%s\"" name
6893 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
6894 and generate_perl_xs () =
6895 generate_header CStyle LGPLv2;
6898 #include \"EXTERN.h\"
6902 #include <guestfs.h>
6905 #define PRId64 \"lld\"
6909 my_newSVll(long long val) {
6910 #ifdef USE_64_BIT_ALL
6911 return newSViv(val);
6915 len = snprintf(buf, 100, \"%%\" PRId64, val);
6916 return newSVpv(buf, len);
6921 #define PRIu64 \"llu\"
6925 my_newSVull(unsigned long long val) {
6926 #ifdef USE_64_BIT_ALL
6927 return newSVuv(val);
6931 len = snprintf(buf, 100, \"%%\" PRIu64, val);
6932 return newSVpv(buf, len);
6936 /* http://www.perlmonks.org/?node_id=680842 */
6938 XS_unpack_charPtrPtr (SV *arg) {
6943 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
6944 croak (\"array reference expected\");
6946 av = (AV *)SvRV (arg);
6947 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
6949 croak (\"malloc failed\");
6951 for (i = 0; i <= av_len (av); i++) {
6952 SV **elem = av_fetch (av, i, 0);
6954 if (!elem || !*elem)
6955 croak (\"missing element in list\");
6957 ret[i] = SvPV_nolen (*elem);
6965 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
6972 RETVAL = guestfs_create ();
6974 croak (\"could not create guestfs handle\");
6975 guestfs_set_error_handler (RETVAL, NULL, NULL);
6988 fun (name, style, _, _, _, _, _) ->
6989 (match fst style with
6990 | RErr -> pr "void\n"
6991 | RInt _ -> pr "SV *\n"
6992 | RInt64 _ -> pr "SV *\n"
6993 | RBool _ -> pr "SV *\n"
6994 | RConstString _ -> pr "SV *\n"
6995 | RConstOptString _ -> pr "SV *\n"
6996 | RString _ -> pr "SV *\n"
6997 | RBufferOut _ -> pr "SV *\n"
6999 | RStruct _ | RStructList _
7001 pr "void\n" (* all lists returned implictly on the stack *)
7003 (* Call and arguments. *)
7005 generate_c_call_args ~handle:"g" ~decl:true style;
7007 pr " guestfs_h *g;\n";
7011 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7014 (* http://www.perlmonks.org/?node_id=554277
7015 * Note that the implicit handle argument means we have
7016 * to add 1 to the ST(x) operator.
7018 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7019 | StringList n -> pr " char **%s;\n" n
7020 | Bool n -> pr " int %s;\n" n
7021 | Int n -> pr " int %s;\n" n
7024 let do_cleanups () =
7027 | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7028 | FileIn _ | FileOut _ -> ()
7029 | StringList n -> pr " free (%s);\n" n
7034 (match fst style with
7039 pr " r = guestfs_%s " name;
7040 generate_c_call_args ~handle:"g" style;
7043 pr " if (r == -1)\n";
7044 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7050 pr " %s = guestfs_%s " n name;
7051 generate_c_call_args ~handle:"g" style;
7054 pr " if (%s == -1)\n" n;
7055 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7056 pr " RETVAL = newSViv (%s);\n" n;
7061 pr " int64_t %s;\n" n;
7063 pr " %s = guestfs_%s " n name;
7064 generate_c_call_args ~handle:"g" style;
7067 pr " if (%s == -1)\n" n;
7068 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7069 pr " RETVAL = my_newSVll (%s);\n" n;
7074 pr " const char *%s;\n" n;
7076 pr " %s = guestfs_%s " n name;
7077 generate_c_call_args ~handle:"g" style;
7080 pr " if (%s == NULL)\n" n;
7081 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7082 pr " RETVAL = newSVpv (%s, 0);\n" n;
7085 | RConstOptString n ->
7087 pr " const char *%s;\n" n;
7089 pr " %s = guestfs_%s " n name;
7090 generate_c_call_args ~handle:"g" style;
7093 pr " if (%s == NULL)\n" n;
7094 pr " RETVAL = &PL_sv_undef;\n";
7096 pr " RETVAL = newSVpv (%s, 0);\n" n;
7101 pr " char *%s;\n" n;
7103 pr " %s = guestfs_%s " n name;
7104 generate_c_call_args ~handle:"g" style;
7107 pr " if (%s == NULL)\n" n;
7108 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7109 pr " RETVAL = newSVpv (%s, 0);\n" n;
7110 pr " free (%s);\n" n;
7113 | RStringList n | RHashtable n ->
7115 pr " char **%s;\n" n;
7118 pr " %s = guestfs_%s " n name;
7119 generate_c_call_args ~handle:"g" style;
7122 pr " if (%s == NULL)\n" n;
7123 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7124 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7125 pr " EXTEND (SP, n);\n";
7126 pr " for (i = 0; i < n; ++i) {\n";
7127 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7128 pr " free (%s[i]);\n" n;
7130 pr " free (%s);\n" n;
7131 | RStruct (n, typ) ->
7132 let cols = cols_of_struct typ in
7133 generate_perl_struct_code typ cols name style n do_cleanups
7134 | RStructList (n, typ) ->
7135 let cols = cols_of_struct typ in
7136 generate_perl_struct_list_code typ cols name style n do_cleanups
7139 pr " char *%s;\n" n;
7140 pr " size_t size;\n";
7142 pr " %s = guestfs_%s " n name;
7143 generate_c_call_args ~handle:"g" style;
7146 pr " if (%s == NULL)\n" n;
7147 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7148 pr " RETVAL = newSVpv (%s, size);\n" n;
7149 pr " free (%s);\n" n;
7157 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7159 pr " struct guestfs_%s_list *%s;\n" typ n;
7163 pr " %s = guestfs_%s " n name;
7164 generate_c_call_args ~handle:"g" style;
7167 pr " if (%s == NULL)\n" n;
7168 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7169 pr " EXTEND (SP, %s->len);\n" n;
7170 pr " for (i = 0; i < %s->len; ++i) {\n" n;
7171 pr " hv = newHV ();\n";
7175 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7176 name (String.length name) n name
7178 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7179 name (String.length name) n name
7181 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7182 name (String.length name) n name n name
7183 | name, (FBytes|FUInt64) ->
7184 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7185 name (String.length name) n name
7187 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7188 name (String.length name) n name
7189 | name, (FInt32|FUInt32) ->
7190 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7191 name (String.length name) n name
7193 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7194 name (String.length name) n name
7195 | name, FOptPercent ->
7196 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7197 name (String.length name) n name
7199 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7201 pr " guestfs_free_%s_list (%s);\n" typ n
7203 and generate_perl_struct_code typ cols name style n do_cleanups =
7205 pr " struct guestfs_%s *%s;\n" typ n;
7207 pr " %s = guestfs_%s " n name;
7208 generate_c_call_args ~handle:"g" style;
7211 pr " if (%s == NULL)\n" n;
7212 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7213 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7215 fun ((name, _) as col) ->
7216 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7220 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7223 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7226 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7228 | name, (FBytes|FUInt64) ->
7229 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7232 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7234 | name, (FInt32|FUInt32) ->
7235 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7238 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7240 | name, FOptPercent ->
7241 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7244 pr " free (%s);\n" n
7246 (* Generate Sys/Guestfs.pm. *)
7247 and generate_perl_pm () =
7248 generate_header HashStyle LGPLv2;
7255 Sys::Guestfs - Perl bindings for libguestfs
7261 my $h = Sys::Guestfs->new ();
7262 $h->add_drive ('guest.img');
7265 $h->mount ('/dev/sda1', '/');
7266 $h->touch ('/hello');
7271 The C<Sys::Guestfs> module provides a Perl XS binding to the
7272 libguestfs API for examining and modifying virtual machine
7275 Amongst the things this is good for: making batch configuration
7276 changes to guests, getting disk used/free statistics (see also:
7277 virt-df), migrating between virtualization systems (see also:
7278 virt-p2v), performing partial backups, performing partial guest
7279 clones, cloning guests and changing registry/UUID/hostname info, and
7282 Libguestfs uses Linux kernel and qemu code, and can access any type of
7283 guest filesystem that Linux and qemu can, including but not limited
7284 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7285 schemes, qcow, qcow2, vmdk.
7287 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7288 LVs, what filesystem is in each LV, etc.). It can also run commands
7289 in the context of the guest. Also you can access filesystems over FTP.
7291 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7292 functions for using libguestfs from Perl, including integration
7297 All errors turn into calls to C<croak> (see L<Carp(3)>).
7305 package Sys::Guestfs;
7311 XSLoader::load ('Sys::Guestfs');
7313 =item $h = Sys::Guestfs->new ();
7315 Create a new guestfs handle.
7321 my $class = ref ($proto) || $proto;
7323 my $self = Sys::Guestfs::_create ();
7324 bless $self, $class;
7330 (* Actions. We only need to print documentation for these as
7331 * they are pulled in from the XS code automatically.
7334 fun (name, style, _, flags, _, _, longdesc) ->
7335 if not (List.mem NotInDocs flags) then (
7336 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7338 generate_perl_prototype name style;
7340 pr "%s\n\n" longdesc;
7341 if List.mem ProtocolLimitWarning flags then
7342 pr "%s\n\n" protocol_limit_warning;
7343 if List.mem DangerWillRobinson flags then
7344 pr "%s\n\n" danger_will_robinson;
7345 match deprecation_notice flags with
7347 | Some txt -> pr "%s\n\n" txt
7349 ) all_functions_sorted;
7361 Copyright (C) 2009 Red Hat Inc.
7365 Please see the file COPYING.LIB for the full license.
7371 L<http://libguestfs.org>,
7372 L<Sys::Guestfs::Lib(3)>.
7377 and generate_perl_prototype name style =
7378 (match fst style with
7386 | RBufferOut n -> pr "$%s = " n
7388 | RHashtable n -> pr "%%%s = " n
7390 | RStructList (n,_) -> pr "@%s = " n
7393 let comma = ref false in
7396 if !comma then pr ", ";
7399 | Pathname n | Device n | Dev_or_Path n | String n
7400 | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7407 (* Generate Python C module. *)
7408 and generate_python_c () =
7409 generate_header CStyle LGPLv2;
7418 #include \"guestfs.h\"
7426 get_handle (PyObject *obj)
7429 assert (obj != Py_None);
7430 return ((Pyguestfs_Object *) obj)->g;
7434 put_handle (guestfs_h *g)
7438 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7441 /* This list should be freed (but not the strings) after use. */
7442 static const char **
7443 get_string_list (PyObject *obj)
7450 if (!PyList_Check (obj)) {
7451 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7455 len = PyList_Size (obj);
7456 r = malloc (sizeof (char *) * (len+1));
7458 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7462 for (i = 0; i < len; ++i)
7463 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7470 put_string_list (char * const * const argv)
7475 for (argc = 0; argv[argc] != NULL; ++argc)
7478 list = PyList_New (argc);
7479 for (i = 0; i < argc; ++i)
7480 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7486 put_table (char * const * const argv)
7488 PyObject *list, *item;
7491 for (argc = 0; argv[argc] != NULL; ++argc)
7494 list = PyList_New (argc >> 1);
7495 for (i = 0; i < argc; i += 2) {
7496 item = PyTuple_New (2);
7497 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7498 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7499 PyList_SetItem (list, i >> 1, item);
7506 free_strings (char **argv)
7510 for (argc = 0; argv[argc] != NULL; ++argc)
7516 py_guestfs_create (PyObject *self, PyObject *args)
7520 g = guestfs_create ();
7522 PyErr_SetString (PyExc_RuntimeError,
7523 \"guestfs.create: failed to allocate handle\");
7526 guestfs_set_error_handler (g, NULL, NULL);
7527 return put_handle (g);
7531 py_guestfs_close (PyObject *self, PyObject *args)
7536 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7538 g = get_handle (py_g);
7542 Py_INCREF (Py_None);
7548 let emit_put_list_function typ =
7549 pr "static PyObject *\n";
7550 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7552 pr " PyObject *list;\n";
7555 pr " list = PyList_New (%ss->len);\n" typ;
7556 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7557 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7558 pr " return list;\n";
7563 (* Structures, turned into Python dictionaries. *)
7566 pr "static PyObject *\n";
7567 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7569 pr " PyObject *dict;\n";
7571 pr " dict = PyDict_New ();\n";
7575 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7576 pr " PyString_FromString (%s->%s));\n"
7579 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7580 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7583 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7584 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
7586 | name, (FBytes|FUInt64) ->
7587 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7588 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
7591 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7592 pr " PyLong_FromLongLong (%s->%s));\n"
7595 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7596 pr " PyLong_FromUnsignedLong (%s->%s));\n"
7599 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7600 pr " PyLong_FromLong (%s->%s));\n"
7602 | name, FOptPercent ->
7603 pr " if (%s->%s >= 0)\n" typ name;
7604 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7605 pr " PyFloat_FromDouble ((double) %s->%s));\n"
7608 pr " Py_INCREF (Py_None);\n";
7609 pr " PyDict_SetItemString (dict, \"%s\", Py_None);" name;
7612 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7613 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7615 pr " return dict;\n";
7621 (* Emit a put_TYPE_list function definition only if that function is used. *)
7624 | typ, (RStructListOnly | RStructAndList) ->
7625 (* generate the function for typ *)
7626 emit_put_list_function typ
7627 | typ, _ -> () (* empty *)
7630 (* Python wrapper functions. *)
7632 fun (name, style, _, _, _, _, _) ->
7633 pr "static PyObject *\n";
7634 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7637 pr " PyObject *py_g;\n";
7638 pr " guestfs_h *g;\n";
7639 pr " PyObject *py_r;\n";
7642 match fst style with
7643 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7644 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7645 | RConstString _ | RConstOptString _ ->
7646 pr " const char *r;\n"; "NULL"
7647 | RString _ -> pr " char *r;\n"; "NULL"
7648 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7649 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7650 | RStructList (_, typ) ->
7651 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7654 pr " size_t size;\n";
7659 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7660 pr " const char *%s;\n" n
7661 | OptString n -> pr " const char *%s;\n" n
7663 pr " PyObject *py_%s;\n" n;
7664 pr " const char **%s;\n" n
7665 | Bool n -> pr " int %s;\n" n
7666 | Int n -> pr " int %s;\n" n
7671 (* Convert the parameters. *)
7672 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
7675 | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7676 | OptString _ -> pr "z"
7677 | StringList _ -> pr "O"
7678 | Bool _ -> pr "i" (* XXX Python has booleans? *)
7681 pr ":guestfs_%s\",\n" name;
7685 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7686 | OptString n -> pr ", &%s" n
7687 | StringList n -> pr ", &py_%s" n
7688 | Bool n -> pr ", &%s" n
7689 | Int n -> pr ", &%s" n
7693 pr " return NULL;\n";
7695 pr " g = get_handle (py_g);\n";
7698 | Pathname _ | Device _ | Dev_or_Path _ | String _
7699 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7701 pr " %s = get_string_list (py_%s);\n" n n;
7702 pr " if (!%s) return NULL;\n" n
7707 pr " r = guestfs_%s " name;
7708 generate_c_call_args ~handle:"g" style;
7713 | Pathname _ | Device _ | Dev_or_Path _ | String _
7714 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7716 pr " free (%s);\n" n
7719 pr " if (r == %s) {\n" error_code;
7720 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7721 pr " return NULL;\n";
7725 (match fst style with
7727 pr " Py_INCREF (Py_None);\n";
7728 pr " py_r = Py_None;\n"
7730 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
7731 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
7732 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
7733 | RConstOptString _ ->
7735 pr " py_r = PyString_FromString (r);\n";
7737 pr " Py_INCREF (Py_None);\n";
7738 pr " py_r = Py_None;\n";
7741 pr " py_r = PyString_FromString (r);\n";
7744 pr " py_r = put_string_list (r);\n";
7745 pr " free_strings (r);\n"
7746 | RStruct (_, typ) ->
7747 pr " py_r = put_%s (r);\n" typ;
7748 pr " guestfs_free_%s (r);\n" typ
7749 | RStructList (_, typ) ->
7750 pr " py_r = put_%s_list (r);\n" typ;
7751 pr " guestfs_free_%s_list (r);\n" typ
7753 pr " py_r = put_table (r);\n";
7754 pr " free_strings (r);\n"
7756 pr " py_r = PyString_FromStringAndSize (r, size);\n";
7760 pr " return py_r;\n";
7765 (* Table of functions. *)
7766 pr "static PyMethodDef methods[] = {\n";
7767 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7768 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7770 fun (name, _, _, _, _, _, _) ->
7771 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7774 pr " { NULL, NULL, 0, NULL }\n";
7778 (* Init function. *)
7781 initlibguestfsmod (void)
7783 static int initialized = 0;
7785 if (initialized) return;
7786 Py_InitModule ((char *) \"libguestfsmod\", methods);
7791 (* Generate Python module. *)
7792 and generate_python_py () =
7793 generate_header HashStyle LGPLv2;
7796 u\"\"\"Python bindings for libguestfs
7799 g = guestfs.GuestFS ()
7800 g.add_drive (\"guest.img\")
7803 parts = g.list_partitions ()
7805 The guestfs module provides a Python binding to the libguestfs API
7806 for examining and modifying virtual machine disk images.
7808 Amongst the things this is good for: making batch configuration
7809 changes to guests, getting disk used/free statistics (see also:
7810 virt-df), migrating between virtualization systems (see also:
7811 virt-p2v), performing partial backups, performing partial guest
7812 clones, cloning guests and changing registry/UUID/hostname info, and
7815 Libguestfs uses Linux kernel and qemu code, and can access any type of
7816 guest filesystem that Linux and qemu can, including but not limited
7817 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7818 schemes, qcow, qcow2, vmdk.
7820 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7821 LVs, what filesystem is in each LV, etc.). It can also run commands
7822 in the context of the guest. Also you can access filesystems over FTP.
7824 Errors which happen while using the API are turned into Python
7825 RuntimeError exceptions.
7827 To create a guestfs handle you usually have to perform the following
7830 # Create the handle, call add_drive at least once, and possibly
7831 # several times if the guest has multiple block devices:
7832 g = guestfs.GuestFS ()
7833 g.add_drive (\"guest.img\")
7835 # Launch the qemu subprocess and wait for it to become ready:
7839 # Now you can issue commands, for example:
7844 import libguestfsmod
7847 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7849 def __init__ (self):
7850 \"\"\"Create a new libguestfs handle.\"\"\"
7851 self._o = libguestfsmod.create ()
7854 libguestfsmod.close (self._o)
7859 fun (name, style, _, flags, _, _, longdesc) ->
7861 generate_py_call_args ~handle:"self" (snd style);
7864 if not (List.mem NotInDocs flags) then (
7865 let doc = replace_str longdesc "C<guestfs_" "C<g." in
7867 match fst style with
7868 | RErr | RInt _ | RInt64 _ | RBool _
7869 | RConstOptString _ | RConstString _
7870 | RString _ | RBufferOut _ -> doc
7872 doc ^ "\n\nThis function returns a list of strings."
7873 | RStruct (_, typ) ->
7874 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7875 | RStructList (_, typ) ->
7876 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
7878 doc ^ "\n\nThis function returns a dictionary." in
7880 if List.mem ProtocolLimitWarning flags then
7881 doc ^ "\n\n" ^ protocol_limit_warning
7884 if List.mem DangerWillRobinson flags then
7885 doc ^ "\n\n" ^ danger_will_robinson
7888 match deprecation_notice flags with
7890 | Some txt -> doc ^ "\n\n" ^ txt in
7891 let doc = pod2text ~width:60 name doc in
7892 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
7893 let doc = String.concat "\n " doc in
7894 pr " u\"\"\"%s\"\"\"\n" doc;
7896 pr " return libguestfsmod.%s " name;
7897 generate_py_call_args ~handle:"self._o" (snd style);
7902 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
7903 and generate_py_call_args ~handle args =
7905 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
7908 (* Useful if you need the longdesc POD text as plain text. Returns a
7911 * Because this is very slow (the slowest part of autogeneration),
7912 * we memoize the results.
7914 and pod2text ~width name longdesc =
7915 let key = width, name, longdesc in
7916 try Hashtbl.find pod2text_memo key
7918 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
7919 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
7921 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
7922 let chan = Unix.open_process_in cmd in
7923 let lines = ref [] in
7925 let line = input_line chan in
7926 if i = 1 then (* discard the first line of output *)
7929 let line = triml line in
7930 lines := line :: !lines;
7933 let lines = try loop 1 with End_of_file -> List.rev !lines in
7934 Unix.unlink filename;
7935 (match Unix.close_process_in chan with
7936 | Unix.WEXITED 0 -> ()
7938 failwithf "pod2text: process exited with non-zero status (%d)" i
7939 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
7940 failwithf "pod2text: process signalled or stopped by signal %d" i
7942 Hashtbl.add pod2text_memo key lines;
7943 let chan = open_out pod2text_memo_filename in
7944 output_value chan pod2text_memo;
7948 (* Generate ruby bindings. *)
7949 and generate_ruby_c () =
7950 generate_header CStyle LGPLv2;
7958 #include \"guestfs.h\"
7960 #include \"extconf.h\"
7962 /* For Ruby < 1.9 */
7964 #define RARRAY_LEN(r) (RARRAY((r))->len)
7967 static VALUE m_guestfs; /* guestfs module */
7968 static VALUE c_guestfs; /* guestfs_h handle */
7969 static VALUE e_Error; /* used for all errors */
7971 static void ruby_guestfs_free (void *p)
7974 guestfs_close ((guestfs_h *) p);
7977 static VALUE ruby_guestfs_create (VALUE m)
7981 g = guestfs_create ();
7983 rb_raise (e_Error, \"failed to create guestfs handle\");
7985 /* Don't print error messages to stderr by default. */
7986 guestfs_set_error_handler (g, NULL, NULL);
7988 /* Wrap it, and make sure the close function is called when the
7991 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
7994 static VALUE ruby_guestfs_close (VALUE gv)
7997 Data_Get_Struct (gv, guestfs_h, g);
7999 ruby_guestfs_free (g);
8000 DATA_PTR (gv) = NULL;
8008 fun (name, style, _, _, _, _, _) ->
8009 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8010 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8013 pr " guestfs_h *g;\n";
8014 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
8016 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8022 | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8023 pr " Check_Type (%sv, T_STRING);\n" n;
8024 pr " const char *%s = StringValueCStr (%sv);\n" n n;
8026 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8027 pr " \"%s\", \"%s\");\n" n name
8029 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8031 pr " char **%s;\n" n;
8032 pr " Check_Type (%sv, T_ARRAY);\n" n;
8034 pr " int i, len;\n";
8035 pr " len = RARRAY_LEN (%sv);\n" n;
8036 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8038 pr " for (i = 0; i < len; ++i) {\n";
8039 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
8040 pr " %s[i] = StringValueCStr (v);\n" n;
8042 pr " %s[len] = NULL;\n" n;
8045 pr " int %s = RTEST (%sv);\n" n n
8047 pr " int %s = NUM2INT (%sv);\n" n n
8052 match fst style with
8053 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
8054 | RInt64 _ -> pr " int64_t r;\n"; "-1"
8055 | RConstString _ | RConstOptString _ ->
8056 pr " const char *r;\n"; "NULL"
8057 | RString _ -> pr " char *r;\n"; "NULL"
8058 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
8059 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
8060 | RStructList (_, typ) ->
8061 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
8064 pr " size_t size;\n";
8068 pr " r = guestfs_%s " name;
8069 generate_c_call_args ~handle:"g" style;
8074 | Pathname _ | Device _ | Dev_or_Path _ | String _
8075 | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8077 pr " free (%s);\n" n
8080 pr " if (r == %s)\n" error_code;
8081 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8084 (match fst style with
8086 pr " return Qnil;\n"
8087 | RInt _ | RBool _ ->
8088 pr " return INT2NUM (r);\n"
8090 pr " return ULL2NUM (r);\n"
8092 pr " return rb_str_new2 (r);\n";
8093 | RConstOptString _ ->
8095 pr " return rb_str_new2 (r);\n";
8097 pr " return Qnil;\n";
8099 pr " VALUE rv = rb_str_new2 (r);\n";
8103 pr " int i, len = 0;\n";
8104 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
8105 pr " VALUE rv = rb_ary_new2 (len);\n";
8106 pr " for (i = 0; r[i] != NULL; ++i) {\n";
8107 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8108 pr " free (r[i]);\n";
8112 | RStruct (_, typ) ->
8113 let cols = cols_of_struct typ in
8114 generate_ruby_struct_code typ cols
8115 | RStructList (_, typ) ->
8116 let cols = cols_of_struct typ in
8117 generate_ruby_struct_list_code typ cols
8119 pr " VALUE rv = rb_hash_new ();\n";
8121 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
8122 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8123 pr " free (r[i]);\n";
8124 pr " free (r[i+1]);\n";
8129 pr " VALUE rv = rb_str_new (r, size);\n";
8139 /* Initialize the module. */
8140 void Init__guestfs ()
8142 m_guestfs = rb_define_module (\"Guestfs\");
8143 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8144 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8146 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8147 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8150 (* Define the rest of the methods. *)
8152 fun (name, style, _, _, _, _, _) ->
8153 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
8154 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8159 (* Ruby code to return a struct. *)
8160 and generate_ruby_struct_code typ cols =
8161 pr " VALUE rv = rb_hash_new ();\n";
8165 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8167 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8169 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8170 | name, (FBytes|FUInt64) ->
8171 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8173 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8175 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8177 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8178 | name, FOptPercent ->
8179 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8180 | name, FChar -> (* XXX wrong? *)
8181 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8183 pr " guestfs_free_%s (r);\n" typ;
8186 (* Ruby code to return a struct list. *)
8187 and generate_ruby_struct_list_code typ cols =
8188 pr " VALUE rv = rb_ary_new2 (r->len);\n";
8190 pr " for (i = 0; i < r->len; ++i) {\n";
8191 pr " VALUE hv = rb_hash_new ();\n";
8195 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8197 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
8199 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8200 | name, (FBytes|FUInt64) ->
8201 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8203 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8205 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8207 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8208 | name, FOptPercent ->
8209 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8210 | name, FChar -> (* XXX wrong? *)
8211 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8213 pr " rb_ary_push (rv, hv);\n";
8215 pr " guestfs_free_%s_list (r);\n" typ;
8218 (* Generate Java bindings GuestFS.java file. *)
8219 and generate_java_java () =
8220 generate_header CStyle LGPLv2;
8223 package com.redhat.et.libguestfs;
8225 import java.util.HashMap;
8226 import com.redhat.et.libguestfs.LibGuestFSException;
8227 import com.redhat.et.libguestfs.PV;
8228 import com.redhat.et.libguestfs.VG;
8229 import com.redhat.et.libguestfs.LV;
8230 import com.redhat.et.libguestfs.Stat;
8231 import com.redhat.et.libguestfs.StatVFS;
8232 import com.redhat.et.libguestfs.IntBool;
8233 import com.redhat.et.libguestfs.Dirent;
8236 * The GuestFS object is a libguestfs handle.
8240 public class GuestFS {
8241 // Load the native code.
8243 System.loadLibrary (\"guestfs_jni\");
8247 * The native guestfs_h pointer.
8252 * Create a libguestfs handle.
8254 * @throws LibGuestFSException
8256 public GuestFS () throws LibGuestFSException
8260 private native long _create () throws LibGuestFSException;
8263 * Close a libguestfs handle.
8265 * You can also leave handles to be collected by the garbage
8266 * collector, but this method ensures that the resources used
8267 * by the handle are freed up immediately. If you call any
8268 * other methods after closing the handle, you will get an
8271 * @throws LibGuestFSException
8273 public void close () throws LibGuestFSException
8279 private native void _close (long g) throws LibGuestFSException;
8281 public void finalize () throws LibGuestFSException
8289 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8290 if not (List.mem NotInDocs flags); then (
8291 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8293 if List.mem ProtocolLimitWarning flags then
8294 doc ^ "\n\n" ^ protocol_limit_warning
8297 if List.mem DangerWillRobinson flags then
8298 doc ^ "\n\n" ^ danger_will_robinson
8301 match deprecation_notice flags with
8303 | Some txt -> doc ^ "\n\n" ^ txt in
8304 let doc = pod2text ~width:60 name doc in
8305 let doc = List.map ( (* RHBZ#501883 *)
8308 | nonempty -> nonempty
8310 let doc = String.concat "\n * " doc in
8313 pr " * %s\n" shortdesc;
8316 pr " * @throws LibGuestFSException\n";
8320 generate_java_prototype ~public:true ~semicolon:false name style;
8323 pr " if (g == 0)\n";
8324 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8327 if fst style <> RErr then pr "return ";
8329 generate_java_call_args ~handle:"g" (snd style);
8333 generate_java_prototype ~privat:true ~native:true name style;
8340 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8341 and generate_java_call_args ~handle args =
8343 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8346 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8347 ?(semicolon=true) name style =
8348 if privat then pr "private ";
8349 if public then pr "public ";
8350 if native then pr "native ";
8353 (match fst style with
8354 | RErr -> pr "void ";
8355 | RInt _ -> pr "int ";
8356 | RInt64 _ -> pr "long ";
8357 | RBool _ -> pr "boolean ";
8358 | RConstString _ | RConstOptString _ | RString _
8359 | RBufferOut _ -> pr "String ";
8360 | RStringList _ -> pr "String[] ";
8361 | RStruct (_, typ) ->
8362 let name = java_name_of_struct typ in
8364 | RStructList (_, typ) ->
8365 let name = java_name_of_struct typ in
8367 | RHashtable _ -> pr "HashMap<String,String> ";
8370 if native then pr "_%s " name else pr "%s " name;
8372 let needs_comma = ref false in
8381 if !needs_comma then pr ", ";
8382 needs_comma := true;
8386 | Device n | Dev_or_Path n
8401 pr " throws LibGuestFSException";
8402 if semicolon then pr ";"
8404 and generate_java_struct jtyp cols =
8405 generate_header CStyle LGPLv2;
8408 package com.redhat.et.libguestfs;
8411 * Libguestfs %s structure.
8423 | name, FBuffer -> pr " public String %s;\n" name
8424 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8425 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8426 | name, FChar -> pr " public char %s;\n" name
8427 | name, FOptPercent ->
8428 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8429 pr " public float %s;\n" name
8434 and generate_java_c () =
8435 generate_header CStyle LGPLv2;
8442 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8443 #include \"guestfs.h\"
8445 /* Note that this function returns. The exception is not thrown
8446 * until after the wrapper function returns.
8449 throw_exception (JNIEnv *env, const char *msg)
8452 cl = (*env)->FindClass (env,
8453 \"com/redhat/et/libguestfs/LibGuestFSException\");
8454 (*env)->ThrowNew (env, cl, msg);
8457 JNIEXPORT jlong JNICALL
8458 Java_com_redhat_et_libguestfs_GuestFS__1create
8459 (JNIEnv *env, jobject obj)
8463 g = guestfs_create ();
8465 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8468 guestfs_set_error_handler (g, NULL, NULL);
8469 return (jlong) (long) g;
8472 JNIEXPORT void JNICALL
8473 Java_com_redhat_et_libguestfs_GuestFS__1close
8474 (JNIEnv *env, jobject obj, jlong jg)
8476 guestfs_h *g = (guestfs_h *) (long) jg;
8483 fun (name, style, _, _, _, _, _) ->
8485 (match fst style with
8486 | RErr -> pr "void ";
8487 | RInt _ -> pr "jint ";
8488 | RInt64 _ -> pr "jlong ";
8489 | RBool _ -> pr "jboolean ";
8490 | RConstString _ | RConstOptString _ | RString _
8491 | RBufferOut _ -> pr "jstring ";
8492 | RStruct _ | RHashtable _ ->
8494 | RStringList _ | RStructList _ ->
8498 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8499 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8501 pr " (JNIEnv *env, jobject obj, jlong jg";
8505 | Device n | Dev_or_Path n
8510 pr ", jstring j%s" n
8512 pr ", jobjectArray j%s" n
8514 pr ", jboolean j%s" n
8520 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8521 let error_code, no_ret =
8522 match fst style with
8523 | RErr -> pr " int r;\n"; "-1", ""
8525 | RInt _ -> pr " int r;\n"; "-1", "0"
8526 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8527 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8528 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8530 pr " jstring jr;\n";
8531 pr " char *r;\n"; "NULL", "NULL"
8533 pr " jobjectArray jr;\n";
8536 pr " jstring jstr;\n";
8537 pr " char **r;\n"; "NULL", "NULL"
8538 | RStruct (_, typ) ->
8539 pr " jobject jr;\n";
8541 pr " jfieldID fl;\n";
8542 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8543 | RStructList (_, typ) ->
8544 pr " jobjectArray jr;\n";
8546 pr " jfieldID fl;\n";
8547 pr " jobject jfl;\n";
8548 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8549 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8551 pr " jstring jr;\n";
8553 pr " size_t size;\n";
8558 | Device n | Dev_or_Path n
8563 pr " const char *%s;\n" n
8565 pr " int %s_len;\n" n;
8566 pr " const char **%s;\n" n
8573 (match fst style with
8574 | RStringList _ | RStructList _ -> true
8575 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8577 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8578 List.exists (function StringList _ -> true | _ -> false) (snd style) in
8584 (* Get the parameters. *)
8588 | Device n | Dev_or_Path n
8592 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8594 (* This is completely undocumented, but Java null becomes
8597 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8599 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8600 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8601 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8602 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8604 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8606 pr " %s[%s_len] = NULL;\n" n n;
8609 pr " %s = j%s;\n" n n
8612 (* Make the call. *)
8613 pr " r = guestfs_%s " name;
8614 generate_c_call_args ~handle:"g" style;
8617 (* Release the parameters. *)
8621 | Device n | Dev_or_Path n
8625 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8628 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8630 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8631 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8633 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8635 pr " free (%s);\n" n
8640 (* Check for errors. *)
8641 pr " if (r == %s) {\n" error_code;
8642 pr " throw_exception (env, guestfs_last_error (g));\n";
8643 pr " return %s;\n" no_ret;
8647 (match fst style with
8649 | RInt _ -> pr " return (jint) r;\n"
8650 | RBool _ -> pr " return (jboolean) r;\n"
8651 | RInt64 _ -> pr " return (jlong) r;\n"
8652 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
8653 | RConstOptString _ ->
8654 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8656 pr " jr = (*env)->NewStringUTF (env, r);\n";
8660 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8661 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8662 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
8663 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8664 pr " for (i = 0; i < r_len; ++i) {\n";
8665 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
8666 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8667 pr " free (r[i]);\n";
8671 | RStruct (_, typ) ->
8672 let jtyp = java_name_of_struct typ in
8673 let cols = cols_of_struct typ in
8674 generate_java_struct_return typ jtyp cols
8675 | RStructList (_, typ) ->
8676 let jtyp = java_name_of_struct typ in
8677 let cols = cols_of_struct typ in
8678 generate_java_struct_list_return typ jtyp cols
8681 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8682 pr " return NULL;\n"
8684 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8693 and generate_java_struct_return typ jtyp cols =
8694 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8695 pr " jr = (*env)->AllocObject (env, cl);\n";
8699 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8700 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8703 pr " char s[33];\n";
8704 pr " memcpy (s, r->%s, 32);\n" name;
8706 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8707 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8711 pr " int len = r->%s_len;\n" name;
8712 pr " char s[len+1];\n";
8713 pr " memcpy (s, r->%s, len);\n" name;
8714 pr " s[len] = 0;\n";
8715 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8716 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8718 | name, (FBytes|FUInt64|FInt64) ->
8719 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8720 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8721 | name, (FUInt32|FInt32) ->
8722 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8723 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8724 | name, FOptPercent ->
8725 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8726 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8728 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8729 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8734 and generate_java_struct_list_return typ jtyp cols =
8735 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8736 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8737 pr " for (i = 0; i < r->len; ++i) {\n";
8738 pr " jfl = (*env)->AllocObject (env, cl);\n";
8742 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8743 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8746 pr " char s[33];\n";
8747 pr " memcpy (s, r->val[i].%s, 32);\n" name;
8749 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8750 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8754 pr " int len = r->val[i].%s_len;\n" name;
8755 pr " char s[len+1];\n";
8756 pr " memcpy (s, r->val[i].%s, len);\n" name;
8757 pr " s[len] = 0;\n";
8758 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8759 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8761 | name, (FBytes|FUInt64|FInt64) ->
8762 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8763 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8764 | name, (FUInt32|FInt32) ->
8765 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8766 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8767 | name, FOptPercent ->
8768 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8769 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8771 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8772 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8774 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8776 pr " guestfs_free_%s_list (r);\n" typ;
8779 and generate_java_makefile_inc () =
8780 generate_header HashStyle GPLv2;
8782 pr "java_built_sources = \\\n";
8785 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8787 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8789 and generate_haskell_hs () =
8790 generate_header HaskellStyle LGPLv2;
8792 (* XXX We only know how to generate partial FFI for Haskell
8793 * at the moment. Please help out!
8795 let can_generate style =
8799 | RInt64 _, _ -> true
8802 | RConstOptString _, _
8808 | RBufferOut _, _ -> false in
8811 {-# INCLUDE <guestfs.h> #-}
8812 {-# LANGUAGE ForeignFunctionInterface #-}
8817 (* List out the names of the actions we want to export. *)
8819 fun (name, style, _, _, _, _, _) ->
8820 if can_generate style then pr ",\n %s" name
8827 import Foreign.C.Types
8829 import Control.Exception
8830 import Data.Typeable
8832 data GuestfsS = GuestfsS -- represents the opaque C struct
8833 type GuestfsP = Ptr GuestfsS -- guestfs_h *
8834 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8836 -- XXX define properly later XXX
8840 data IntBool = IntBool
8842 data StatVFS = StatVFS
8843 data Hashtable = Hashtable
8845 foreign import ccall unsafe \"guestfs_create\" c_create
8847 foreign import ccall unsafe \"&guestfs_close\" c_close
8848 :: FunPtr (GuestfsP -> IO ())
8849 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8850 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8852 create :: IO GuestfsH
8855 c_set_error_handler p nullPtr nullPtr
8856 h <- newForeignPtr c_close p
8859 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8860 :: GuestfsP -> IO CString
8862 -- last_error :: GuestfsH -> IO (Maybe String)
8863 -- last_error h = do
8864 -- str <- withForeignPtr h (\\p -> c_last_error p)
8865 -- maybePeek peekCString str
8867 last_error :: GuestfsH -> IO (String)
8869 str <- withForeignPtr h (\\p -> c_last_error p)
8871 then return \"no error\"
8872 else peekCString str
8876 (* Generate wrappers for each foreign function. *)
8878 fun (name, style, _, _, _, _, _) ->
8879 if can_generate style then (
8880 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8882 generate_haskell_prototype ~handle:"GuestfsP" style;
8886 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
8888 pr "%s %s = do\n" name
8889 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
8891 (* Convert pointer arguments using with* functions. *)
8896 | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
8897 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
8898 | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
8899 | Bool _ | Int _ -> ()
8901 (* Convert integer arguments. *)
8905 | Bool n -> sprintf "(fromBool %s)" n
8906 | Int n -> sprintf "(fromIntegral %s)" n
8907 | FileIn n | FileOut n
8908 | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n -> n
8910 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
8911 (String.concat " " ("p" :: args));
8912 (match fst style with
8913 | RErr | RInt _ | RInt64 _ | RBool _ ->
8914 pr " if (r == -1)\n";
8916 pr " err <- last_error h\n";
8918 | RConstString _ | RConstOptString _ | RString _
8919 | RStringList _ | RStruct _
8920 | RStructList _ | RHashtable _ | RBufferOut _ ->
8921 pr " if (r == nullPtr)\n";
8923 pr " err <- last_error h\n";
8926 (match fst style with
8928 pr " else return ()\n"
8930 pr " else return (fromIntegral r)\n"
8932 pr " else return (fromIntegral r)\n"
8934 pr " else return (toBool r)\n"
8943 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
8949 and generate_haskell_prototype ~handle ?(hs = false) style =
8951 let string = if hs then "String" else "CString" in
8952 let int = if hs then "Int" else "CInt" in
8953 let bool = if hs then "Bool" else "CInt" in
8954 let int64 = if hs then "Integer" else "Int64" in
8958 | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
8959 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
8960 | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
8961 | Bool _ -> pr "%s" bool
8962 | Int _ -> pr "%s" int
8963 | FileIn _ -> pr "%s" string
8964 | FileOut _ -> pr "%s" string
8969 (match fst style with
8970 | RErr -> if not hs then pr "CInt"
8971 | RInt _ -> pr "%s" int
8972 | RInt64 _ -> pr "%s" int64
8973 | RBool _ -> pr "%s" bool
8974 | RConstString _ -> pr "%s" string
8975 | RConstOptString _ -> pr "Maybe %s" string
8976 | RString _ -> pr "%s" string
8977 | RStringList _ -> pr "[%s]" string
8978 | RStruct (_, typ) ->
8979 let name = java_name_of_struct typ in
8981 | RStructList (_, typ) ->
8982 let name = java_name_of_struct typ in
8984 | RHashtable _ -> pr "Hashtable"
8985 | RBufferOut _ -> pr "%s" string
8989 and generate_bindtests () =
8990 generate_header CStyle LGPLv2;
8995 #include <inttypes.h>
8998 #include \"guestfs.h\"
8999 #include \"guestfs_protocol.h\"
9001 #define error guestfs_error
9002 #define safe_calloc guestfs_safe_calloc
9003 #define safe_malloc guestfs_safe_malloc
9006 print_strings (char * const* const argv)
9011 for (argc = 0; argv[argc] != NULL; ++argc) {
9012 if (argc > 0) printf (\", \");
9013 printf (\"\\\"%%s\\\"\", argv[argc]);
9018 /* The test0 function prints its parameters to stdout. */
9022 match test_functions with
9023 | [] -> assert false
9024 | test0 :: tests -> test0, tests in
9027 let (name, style, _, _, _, _, _) = test0 in
9028 generate_prototype ~extern:false ~semicolon:false ~newline:true
9029 ~handle:"g" ~prefix:"guestfs_" name style;
9034 | Device n | Dev_or_Path n
9037 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
9038 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9039 | StringList n -> pr " print_strings (%s);\n" n
9040 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9041 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
9043 pr " /* Java changes stdout line buffering so we need this: */\n";
9044 pr " fflush (stdout);\n";
9050 fun (name, style, _, _, _, _, _) ->
9051 if String.sub name (String.length name - 3) 3 <> "err" then (
9052 pr "/* Test normal return. */\n";
9053 generate_prototype ~extern:false ~semicolon:false ~newline:true
9054 ~handle:"g" ~prefix:"guestfs_" name style;
9056 (match fst style with
9061 pr " sscanf (val, \"%%d\", &r);\n";
9065 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
9068 pr " return strcmp (val, \"true\") == 0;\n"
9070 | RConstOptString _ ->
9071 (* Can't return the input string here. Return a static
9072 * string so we ensure we get a segfault if the caller
9075 pr " return \"static string\";\n"
9077 pr " return strdup (val);\n"
9079 pr " char **strs;\n";
9081 pr " sscanf (val, \"%%d\", &n);\n";
9082 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9083 pr " for (i = 0; i < n; ++i) {\n";
9084 pr " strs[i] = safe_malloc (g, 16);\n";
9085 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
9087 pr " strs[n] = NULL;\n";
9088 pr " return strs;\n"
9089 | RStruct (_, typ) ->
9090 pr " struct guestfs_%s *r;\n" typ;
9091 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9093 | RStructList (_, typ) ->
9094 pr " struct guestfs_%s_list *r;\n" typ;
9095 pr " r = safe_calloc (g, sizeof *r, 1);\n";
9096 pr " sscanf (val, \"%%d\", &r->len);\n";
9097 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9100 pr " char **strs;\n";
9102 pr " sscanf (val, \"%%d\", &n);\n";
9103 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9104 pr " for (i = 0; i < n; ++i) {\n";
9105 pr " strs[i*2] = safe_malloc (g, 16);\n";
9106 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
9107 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
9108 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9110 pr " strs[n*2] = NULL;\n";
9111 pr " return strs;\n"
9113 pr " return strdup (val);\n"
9118 pr "/* Test error return. */\n";
9119 generate_prototype ~extern:false ~semicolon:false ~newline:true
9120 ~handle:"g" ~prefix:"guestfs_" name style;
9122 pr " error (g, \"error\");\n";
9123 (match fst style with
9124 | RErr | RInt _ | RInt64 _ | RBool _ ->
9126 | RConstString _ | RConstOptString _
9127 | RString _ | RStringList _ | RStruct _
9131 pr " return NULL;\n"
9138 and generate_ocaml_bindtests () =
9139 generate_header OCamlStyle GPLv2;
9143 let g = Guestfs.create () in
9150 | CallString s -> "\"" ^ s ^ "\""
9151 | CallOptString None -> "None"
9152 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9153 | CallStringList xs ->
9154 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9155 | CallInt i when i >= 0 -> string_of_int i
9156 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9157 | CallBool b -> string_of_bool b
9162 generate_lang_bindtests (
9163 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
9166 pr "print_endline \"EOF\"\n"
9168 and generate_perl_bindtests () =
9169 pr "#!/usr/bin/perl -w\n";
9170 generate_header HashStyle GPLv2;
9177 my $g = Sys::Guestfs->new ();
9181 String.concat ", " (
9184 | CallString s -> "\"" ^ s ^ "\""
9185 | CallOptString None -> "undef"
9186 | CallOptString (Some s) -> sprintf "\"%s\"" s
9187 | CallStringList xs ->
9188 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9189 | CallInt i -> string_of_int i
9190 | CallBool b -> if b then "1" else "0"
9195 generate_lang_bindtests (
9196 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9199 pr "print \"EOF\\n\"\n"
9201 and generate_python_bindtests () =
9202 generate_header HashStyle GPLv2;
9207 g = guestfs.GuestFS ()
9211 String.concat ", " (
9214 | CallString s -> "\"" ^ s ^ "\""
9215 | CallOptString None -> "None"
9216 | CallOptString (Some s) -> sprintf "\"%s\"" s
9217 | CallStringList xs ->
9218 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9219 | CallInt i -> string_of_int i
9220 | CallBool b -> if b then "1" else "0"
9225 generate_lang_bindtests (
9226 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9229 pr "print \"EOF\"\n"
9231 and generate_ruby_bindtests () =
9232 generate_header HashStyle GPLv2;
9237 g = Guestfs::create()
9241 String.concat ", " (
9244 | CallString s -> "\"" ^ s ^ "\""
9245 | CallOptString None -> "nil"
9246 | CallOptString (Some s) -> sprintf "\"%s\"" s
9247 | CallStringList xs ->
9248 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9249 | CallInt i -> string_of_int i
9250 | CallBool b -> string_of_bool b
9255 generate_lang_bindtests (
9256 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9259 pr "print \"EOF\\n\"\n"
9261 and generate_java_bindtests () =
9262 generate_header CStyle GPLv2;
9265 import com.redhat.et.libguestfs.*;
9267 public class Bindtests {
9268 public static void main (String[] argv)
9271 GuestFS g = new GuestFS ();
9275 String.concat ", " (
9278 | CallString s -> "\"" ^ s ^ "\""
9279 | CallOptString None -> "null"
9280 | CallOptString (Some s) -> sprintf "\"%s\"" s
9281 | CallStringList xs ->
9283 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9284 | CallInt i -> string_of_int i
9285 | CallBool b -> string_of_bool b
9290 generate_lang_bindtests (
9291 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9295 System.out.println (\"EOF\");
9297 catch (Exception exn) {
9298 System.err.println (exn);
9305 and generate_haskell_bindtests () =
9306 generate_header HaskellStyle GPLv2;
9309 module Bindtests where
9310 import qualified Guestfs
9320 | CallString s -> "\"" ^ s ^ "\""
9321 | CallOptString None -> "Nothing"
9322 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9323 | CallStringList xs ->
9324 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9325 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9326 | CallInt i -> string_of_int i
9327 | CallBool true -> "True"
9328 | CallBool false -> "False"
9333 generate_lang_bindtests (
9334 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9337 pr " putStrLn \"EOF\"\n"
9339 (* Language-independent bindings tests - we do it this way to
9340 * ensure there is parity in testing bindings across all languages.
9342 and generate_lang_bindtests call =
9343 call "test0" [CallString "abc"; CallOptString (Some "def");
9344 CallStringList []; CallBool false;
9345 CallInt 0; CallString "123"; CallString "456"];
9346 call "test0" [CallString "abc"; CallOptString None;
9347 CallStringList []; CallBool false;
9348 CallInt 0; CallString "123"; CallString "456"];
9349 call "test0" [CallString ""; CallOptString (Some "def");
9350 CallStringList []; CallBool false;
9351 CallInt 0; CallString "123"; CallString "456"];
9352 call "test0" [CallString ""; CallOptString (Some "");
9353 CallStringList []; CallBool false;
9354 CallInt 0; CallString "123"; CallString "456"];
9355 call "test0" [CallString "abc"; CallOptString (Some "def");
9356 CallStringList ["1"]; CallBool false;
9357 CallInt 0; CallString "123"; CallString "456"];
9358 call "test0" [CallString "abc"; CallOptString (Some "def");
9359 CallStringList ["1"; "2"]; CallBool false;
9360 CallInt 0; CallString "123"; CallString "456"];
9361 call "test0" [CallString "abc"; CallOptString (Some "def");
9362 CallStringList ["1"]; CallBool true;
9363 CallInt 0; CallString "123"; CallString "456"];
9364 call "test0" [CallString "abc"; CallOptString (Some "def");
9365 CallStringList ["1"]; CallBool false;
9366 CallInt (-1); CallString "123"; CallString "456"];
9367 call "test0" [CallString "abc"; CallOptString (Some "def");
9368 CallStringList ["1"]; CallBool false;
9369 CallInt (-2); CallString "123"; CallString "456"];
9370 call "test0" [CallString "abc"; CallOptString (Some "def");
9371 CallStringList ["1"]; CallBool false;
9372 CallInt 1; CallString "123"; CallString "456"];
9373 call "test0" [CallString "abc"; CallOptString (Some "def");
9374 CallStringList ["1"]; CallBool false;
9375 CallInt 2; CallString "123"; CallString "456"];
9376 call "test0" [CallString "abc"; CallOptString (Some "def");
9377 CallStringList ["1"]; CallBool false;
9378 CallInt 4095; CallString "123"; CallString "456"];
9379 call "test0" [CallString "abc"; CallOptString (Some "def");
9380 CallStringList ["1"]; CallBool false;
9381 CallInt 0; CallString ""; CallString ""]
9383 (* XXX Add here tests of the return and error functions. *)
9385 (* This is used to generate the src/MAX_PROC_NR file which
9386 * contains the maximum procedure number, a surrogate for the
9387 * ABI version number. See src/Makefile.am for the details.
9389 and generate_max_proc_nr () =
9390 let proc_nrs = List.map (
9391 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9392 ) daemon_functions in
9394 let max_proc_nr = List.fold_left max 0 proc_nrs in
9396 pr "%d\n" max_proc_nr
9398 let output_to filename =
9399 let filename_new = filename ^ ".new" in
9400 chan := open_out filename_new;
9405 (* Is the new file different from the current file? *)
9406 if Sys.file_exists filename && files_equal filename filename_new then
9407 Unix.unlink filename_new (* same, so skip it *)
9409 (* different, overwrite old one *)
9410 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9411 Unix.rename filename_new filename;
9412 Unix.chmod filename 0o444;
9413 printf "written %s\n%!" filename;
9422 if not (Sys.file_exists "HACKING") then (
9424 You are probably running this from the wrong directory.
9425 Run it from the top source directory using the command
9431 let close = output_to "src/guestfs_protocol.x" in
9435 let close = output_to "src/guestfs-structs.h" in
9436 generate_structs_h ();
9439 let close = output_to "src/guestfs-actions.h" in
9440 generate_actions_h ();
9443 let close = output_to "src/guestfs-actions.c" in
9444 generate_client_actions ();
9447 let close = output_to "daemon/actions.h" in
9448 generate_daemon_actions_h ();
9451 let close = output_to "daemon/stubs.c" in
9452 generate_daemon_actions ();
9455 let close = output_to "daemon/names.c" in
9456 generate_daemon_names ();
9459 let close = output_to "capitests/tests.c" in
9463 let close = output_to "src/guestfs-bindtests.c" in
9464 generate_bindtests ();
9467 let close = output_to "fish/cmds.c" in
9468 generate_fish_cmds ();
9471 let close = output_to "fish/completion.c" in
9472 generate_fish_completion ();
9475 let close = output_to "guestfs-structs.pod" in
9476 generate_structs_pod ();
9479 let close = output_to "guestfs-actions.pod" in
9480 generate_actions_pod ();
9483 let close = output_to "guestfish-actions.pod" in
9484 generate_fish_actions_pod ();
9487 let close = output_to "ocaml/guestfs.mli" in
9488 generate_ocaml_mli ();
9491 let close = output_to "ocaml/guestfs.ml" in
9492 generate_ocaml_ml ();
9495 let close = output_to "ocaml/guestfs_c_actions.c" in
9496 generate_ocaml_c ();
9499 let close = output_to "ocaml/bindtests.ml" in
9500 generate_ocaml_bindtests ();
9503 let close = output_to "perl/Guestfs.xs" in
9504 generate_perl_xs ();
9507 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9508 generate_perl_pm ();
9511 let close = output_to "perl/bindtests.pl" in
9512 generate_perl_bindtests ();
9515 let close = output_to "python/guestfs-py.c" in
9516 generate_python_c ();
9519 let close = output_to "python/guestfs.py" in
9520 generate_python_py ();
9523 let close = output_to "python/bindtests.py" in
9524 generate_python_bindtests ();
9527 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9531 let close = output_to "ruby/bindtests.rb" in
9532 generate_ruby_bindtests ();
9535 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9536 generate_java_java ();
9541 let cols = cols_of_struct typ in
9542 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9543 let close = output_to filename in
9544 generate_java_struct jtyp cols;
9548 let close = output_to "java/Makefile.inc" in
9549 generate_java_makefile_inc ();
9552 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9556 let close = output_to "java/Bindtests.java" in
9557 generate_java_bindtests ();
9560 let close = output_to "haskell/Guestfs.hs" in
9561 generate_haskell_hs ();
9564 let close = output_to "haskell/Bindtests.hs" in
9565 generate_haskell_bindtests ();
9568 let close = output_to "src/MAX_PROC_NR" in
9569 generate_max_proc_nr ();
9572 (* Always generate this file last, and unconditionally. It's used
9573 * by the Makefile to know when we must re-run the generator.
9575 let chan = open_out "src/stamp-generator" in