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 | OptString of string (* const char *name, may be NULL *)
138 | StringList of string(* list of strings (each string cannot be NULL) *)
139 | Bool of string (* boolean *)
140 | Int of string (* int (smallish ints, signed, <= 31 bits) *)
141 (* These are treated as filenames (simple string parameters) in
142 * the C API and bindings. But in the RPC protocol, we transfer
143 * the actual file content up to or down from the daemon.
144 * FileIn: local machine -> daemon (in request)
145 * FileOut: daemon -> local machine (in reply)
146 * In guestfish (only), the special name "-" means read from
147 * stdin or write to stdout.
152 (* Opaque buffer which can contain arbitrary 8 bit data.
153 * In the C API, this is expressed as <char *, int> pair.
154 * Most other languages have a string type which can contain
155 * ASCII NUL. We use whatever type is appropriate for each
157 * Buffers are limited by the total message size. To transfer
158 * large blocks of data, use FileIn/FileOut parameters instead.
159 * To return an arbitrary buffer, use RBufferOut.
165 | ProtocolLimitWarning (* display warning about protocol size limits *)
166 | DangerWillRobinson (* flags particularly dangerous commands *)
167 | FishAlias of string (* provide an alias for this cmd in guestfish *)
168 | FishAction of string (* call this function in guestfish *)
169 | NotInFish (* do not export via guestfish *)
170 | NotInDocs (* do not add this function to documentation *)
171 | DeprecatedBy of string (* function is deprecated, use .. instead *)
173 (* You can supply zero or as many tests as you want per API call.
175 * Note that the test environment has 3 block devices, of size 500MB,
176 * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
177 * a fourth squashfs block device with some known files on it (/dev/sdd).
179 * Note for partitioning purposes, the 500MB device has 1015 cylinders.
180 * Number of cylinders was 63 for IDE emulated disks with precisely
181 * the same size. How exactly this is calculated is a mystery.
183 * The squashfs block device (/dev/sdd) comes from images/test.sqsh.
185 * To be able to run the tests in a reasonable amount of time,
186 * the virtual machine and block devices are reused between tests.
187 * So don't try testing kill_subprocess :-x
189 * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
191 * Don't assume anything about the previous contents of the block
192 * devices. Use 'Init*' to create some initial scenarios.
194 * You can add a prerequisite clause to any individual test. This
195 * is a run-time check, which, if it fails, causes the test to be
196 * skipped. Useful if testing a command which might not work on
197 * all variations of libguestfs builds. A test that has prerequisite
198 * of 'Always' is run unconditionally.
200 * In addition, packagers can skip individual tests by setting the
201 * environment variables: eg:
202 * SKIP_TEST_<CMD>_<NUM>=1 SKIP_TEST_COMMAND_3=1 (skips test #3 of command)
203 * SKIP_TEST_<CMD>=1 SKIP_TEST_ZEROFREE=1 (skips all zerofree tests)
205 type tests = (test_init * test_prereq * test) list
207 (* Run the command sequence and just expect nothing to fail. *)
210 (* Run the command sequence and expect the output of the final
211 * command to be the string.
213 | TestOutput of seq * string
215 (* Run the command sequence and expect the output of the final
216 * command to be the list of strings.
218 | TestOutputList of seq * string list
220 (* Run the command sequence and expect the output of the final
221 * command to be the list of block devices (could be either
222 * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
223 * character of each string).
225 | TestOutputListOfDevices of seq * string list
227 (* Run the command sequence and expect the output of the final
228 * command to be the integer.
230 | TestOutputInt of seq * int
232 (* Run the command sequence and expect the output of the final
233 * command to be <op> <int>, eg. ">=", "1".
235 | TestOutputIntOp of seq * string * int
237 (* Run the command sequence and expect the output of the final
238 * command to be a true value (!= 0 or != NULL).
240 | TestOutputTrue of seq
242 (* Run the command sequence and expect the output of the final
243 * command to be a false value (== 0 or == NULL, but not an error).
245 | TestOutputFalse of seq
247 (* Run the command sequence and expect the output of the final
248 * command to be a list of the given length (but don't care about
251 | TestOutputLength of seq * int
253 (* Run the command sequence and expect the output of the final
254 * command to be a buffer (RBufferOut), ie. string + size.
256 | TestOutputBuffer of seq * string
258 (* Run the command sequence and expect the output of the final
259 * command to be a structure.
261 | TestOutputStruct of seq * test_field_compare list
263 (* Run the command sequence and expect the final command (only)
266 | TestLastFail of seq
268 and test_field_compare =
269 | CompareWithInt of string * int
270 | CompareWithIntOp of string * string * int
271 | CompareWithString of string * string
272 | CompareFieldsIntEq of string * string
273 | CompareFieldsStrEq of string * string
275 (* Test prerequisites. *)
277 (* Test always runs. *)
280 (* Test is currently disabled - eg. it fails, or it tests some
281 * unimplemented feature.
285 (* 'string' is some C code (a function body) that should return
286 * true or false. The test will run if the code returns true.
290 (* As for 'If' but the test runs _unless_ the code returns true. *)
293 (* Some initial scenarios for testing. *)
295 (* Do nothing, block devices could contain random stuff including
296 * LVM PVs, and some filesystems might be mounted. This is usually
301 (* Block devices are empty and no filesystems are mounted. *)
304 (* /dev/sda contains a single partition /dev/sda1, with random
305 * content. /dev/sdb and /dev/sdc may have random content.
310 (* /dev/sda contains a single partition /dev/sda1, which is formatted
311 * as ext2, empty [except for lost+found] and mounted on /.
312 * /dev/sdb and /dev/sdc may have random content.
318 * /dev/sda1 (is a PV):
319 * /dev/VG/LV (size 8MB):
320 * formatted as ext2, empty [except for lost+found], mounted on /
321 * /dev/sdb and /dev/sdc may have random content.
325 (* /dev/sdd (the squashfs, see images/ directory in source)
330 (* Sequence of commands for testing. *)
332 and cmd = string list
334 (* Note about long descriptions: When referring to another
335 * action, use the format C<guestfs_other> (ie. the full name of
336 * the C function). This will be replaced as appropriate in other
339 * Apart from that, long descriptions are just perldoc paragraphs.
342 (* These test functions are used in the language binding tests. *)
344 let test_all_args = [
347 StringList "strlist";
354 let test_all_rets = [
355 (* except for RErr, which is tested thoroughly elsewhere *)
356 "test0rint", RInt "valout";
357 "test0rint64", RInt64 "valout";
358 "test0rbool", RBool "valout";
359 "test0rconststring", RConstString "valout";
360 "test0rconstoptstring", RConstOptString "valout";
361 "test0rstring", RString "valout";
362 "test0rstringlist", RStringList "valout";
363 "test0rstruct", RStruct ("valout", "lvm_pv");
364 "test0rstructlist", RStructList ("valout", "lvm_pv");
365 "test0rhashtable", RHashtable "valout";
368 let test_functions = [
369 ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
371 "internal test function - do not use",
373 This is an internal test function which is used to test whether
374 the automatically generated bindings can handle every possible
375 parameter type correctly.
377 It echos the contents of each parameter to stdout.
379 You probably don't want to call this function.");
383 [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
385 "internal test function - do not use",
387 This is an internal test function which is used to test whether
388 the automatically generated bindings can handle every possible
389 return type correctly.
391 It converts string C<val> to the return type.
393 You probably don't want to call this function.");
394 (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
396 "internal test function - do not use",
398 This is an internal test function which is used to test whether
399 the automatically generated bindings can handle every possible
400 return type correctly.
402 This function always returns an error.
404 You probably don't want to call this function.")]
408 (* non_daemon_functions are any functions which don't get processed
409 * in the daemon, eg. functions for setting and getting local
410 * configuration values.
413 let non_daemon_functions = test_functions @ [
414 ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
416 "launch the qemu subprocess",
418 Internally libguestfs is implemented by running a virtual machine
421 You should call this after configuring the handle
422 (eg. adding drives) but before performing any actions.");
424 ("wait_ready", (RErr, []), -1, [NotInFish],
426 "wait until the qemu subprocess launches",
428 Internally libguestfs is implemented by running a virtual machine
431 You should call this after C<guestfs_launch> to wait for the launch
434 ("kill_subprocess", (RErr, []), -1, [],
436 "kill the qemu subprocess",
438 This kills the qemu subprocess. You should never need to call this.");
440 ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
442 "add an image to examine or modify",
444 This function adds a virtual machine disk image C<filename> to the
445 guest. The first time you call this function, the disk appears as IDE
446 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
449 You don't necessarily need to be root when using libguestfs. However
450 you obviously do need sufficient permissions to access the filename
451 for whatever operations you want to perform (ie. read access if you
452 just want to read the image or write access if you want to modify the
455 This is equivalent to the qemu parameter
456 C<-drive file=filename,cache=off,if=...>.
458 Note that this call checks for the existence of C<filename>. This
459 stops you from specifying other types of drive which are supported
460 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
461 the general C<guestfs_config> call instead.");
463 ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
465 "add a CD-ROM disk image to examine",
467 This function adds a virtual CD-ROM disk image to the guest.
469 This is equivalent to the qemu parameter C<-cdrom filename>.
471 Note that this call checks for the existence of C<filename>. This
472 stops you from specifying other types of drive which are supported
473 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
474 the general C<guestfs_config> call instead.");
476 ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
478 "add a drive in snapshot mode (read-only)",
480 This adds a drive in snapshot mode, making it effectively
483 Note that writes to the device are allowed, and will be seen for
484 the duration of the guestfs handle, but they are written
485 to a temporary file which is discarded as soon as the guestfs
486 handle is closed. We don't currently have any method to enable
487 changes to be committed, although qemu can support this.
489 This is equivalent to the qemu parameter
490 C<-drive file=filename,snapshot=on,if=...>.
492 Note that this call checks for the existence of C<filename>. This
493 stops you from specifying other types of drive which are supported
494 by qemu such as C<nbd:> and C<http:> URLs. To specify those, use
495 the general C<guestfs_config> call instead.");
497 ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
499 "add qemu parameters",
501 This can be used to add arbitrary qemu command line parameters
502 of the form C<-param value>. Actually it's not quite arbitrary - we
503 prevent you from setting some parameters which would interfere with
504 parameters that we use.
506 The first character of C<param> string must be a C<-> (dash).
508 C<value> can be NULL.");
510 ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
512 "set the qemu binary",
514 Set the qemu binary that we will use.
516 The default is chosen when the library was compiled by the
519 You can also override this by setting the C<LIBGUESTFS_QEMU>
520 environment variable.
522 Setting C<qemu> to C<NULL> restores the default qemu binary.");
524 ("get_qemu", (RConstString "qemu", []), -1, [],
525 [InitNone, Always, TestRun (
527 "get the qemu binary",
529 Return the current qemu binary.
531 This is always non-NULL. If it wasn't set already, then this will
532 return the default qemu binary name.");
534 ("set_path", (RErr, [String "path"]), -1, [FishAlias "path"],
536 "set the search path",
538 Set the path that libguestfs searches for kernel and initrd.img.
540 The default is C<$libdir/guestfs> unless overridden by setting
541 C<LIBGUESTFS_PATH> environment variable.
543 Setting C<path> to C<NULL> restores the default path.");
545 ("get_path", (RConstString "path", []), -1, [],
546 [InitNone, Always, TestRun (
548 "get the search path",
550 Return the current search path.
552 This is always non-NULL. If it wasn't set already, then this will
553 return the default path.");
555 ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
557 "add options to kernel command line",
559 This function is used to add additional options to the
560 guest kernel command line.
562 The default is C<NULL> unless overridden by setting
563 C<LIBGUESTFS_APPEND> environment variable.
565 Setting C<append> to C<NULL> means I<no> additional options
566 are passed (libguestfs always adds a few of its own).");
568 ("get_append", (RConstOptString "append", []), -1, [],
569 (* This cannot be tested with the current framework. The
570 * function can return NULL in normal operations, which the
571 * test framework interprets as an error.
574 "get the additional kernel options",
576 Return the additional kernel options which are added to the
577 guest kernel command line.
579 If C<NULL> then no options are added.");
581 ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
585 If C<autosync> is true, this enables autosync. Libguestfs will make a
586 best effort attempt to run C<guestfs_umount_all> followed by
587 C<guestfs_sync> when the handle is closed
588 (also if the program exits without closing handles).
590 This is disabled by default (except in guestfish where it is
591 enabled by default).");
593 ("get_autosync", (RBool "autosync", []), -1, [],
594 [InitNone, Always, TestRun (
595 [["get_autosync"]])],
598 Get the autosync flag.");
600 ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
604 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
606 Verbose messages are disabled unless the environment variable
607 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
609 ("get_verbose", (RBool "verbose", []), -1, [],
613 This returns the verbose messages flag.");
615 ("is_ready", (RBool "ready", []), -1, [],
616 [InitNone, Always, TestOutputTrue (
618 "is ready to accept commands",
620 This returns true iff this handle is ready to accept commands
621 (in the C<READY> state).
623 For more information on states, see L<guestfs(3)>.");
625 ("is_config", (RBool "config", []), -1, [],
626 [InitNone, Always, TestOutputFalse (
628 "is in configuration state",
630 This returns true iff this handle is being configured
631 (in the C<CONFIG> state).
633 For more information on states, see L<guestfs(3)>.");
635 ("is_launching", (RBool "launching", []), -1, [],
636 [InitNone, Always, TestOutputFalse (
637 [["is_launching"]])],
638 "is launching subprocess",
640 This returns true iff this handle is launching the subprocess
641 (in the C<LAUNCHING> state).
643 For more information on states, see L<guestfs(3)>.");
645 ("is_busy", (RBool "busy", []), -1, [],
646 [InitNone, Always, TestOutputFalse (
648 "is busy processing a command",
650 This returns true iff this handle is busy processing a command
651 (in the C<BUSY> state).
653 For more information on states, see L<guestfs(3)>.");
655 ("get_state", (RInt "state", []), -1, [],
657 "get the current state",
659 This returns the current state as an opaque integer. This is
660 only useful for printing debug and internal error messages.
662 For more information on states, see L<guestfs(3)>.");
664 ("set_busy", (RErr, []), -1, [NotInFish],
668 This sets the state to C<BUSY>. This is only used when implementing
669 actions using the low-level API.
671 For more information on states, see L<guestfs(3)>.");
673 ("set_ready", (RErr, []), -1, [NotInFish],
675 "set state to ready",
677 This sets the state to C<READY>. This is only used when implementing
678 actions using the low-level API.
680 For more information on states, see L<guestfs(3)>.");
682 ("end_busy", (RErr, []), -1, [NotInFish],
684 "leave the busy state",
686 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
687 state as is. This is only used when implementing
688 actions using the low-level API.
690 For more information on states, see L<guestfs(3)>.");
692 ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
693 [InitNone, Always, TestOutputInt (
694 [["set_memsize"; "500"];
695 ["get_memsize"]], 500)],
696 "set memory allocated to the qemu subprocess",
698 This sets the memory size in megabytes allocated to the
699 qemu subprocess. This only has any effect if called before
702 You can also change this by setting the environment
703 variable C<LIBGUESTFS_MEMSIZE> before the handle is
706 For more information on the architecture of libguestfs,
707 see L<guestfs(3)>.");
709 ("get_memsize", (RInt "memsize", []), -1, [],
710 [InitNone, Always, TestOutputIntOp (
711 [["get_memsize"]], ">=", 256)],
712 "get memory allocated to the qemu subprocess",
714 This gets the memory size in megabytes allocated to the
717 If C<guestfs_set_memsize> was not called
718 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
719 then this returns the compiled-in default value for memsize.
721 For more information on the architecture of libguestfs,
722 see L<guestfs(3)>.");
724 ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
725 [InitNone, Always, TestOutputIntOp (
726 [["get_pid"]], ">=", 1)],
727 "get PID of qemu subprocess",
729 Return the process ID of the qemu subprocess. If there is no
730 qemu subprocess, then this will return an error.
732 This is an internal call used for debugging and testing.");
734 ("version", (RStruct ("version", "version"), []), -1, [],
735 [InitNone, Always, TestOutputStruct (
736 [["version"]], [CompareWithInt ("major", 1)])],
737 "get the library version number",
739 Return the libguestfs version number that the program is linked
742 Note that because of dynamic linking this is not necessarily
743 the version of libguestfs that you compiled against. You can
744 compile the program, and then at runtime dynamically link
745 against a completely different C<libguestfs.so> library.
747 This call was added in version C<1.0.58>. In previous
748 versions of libguestfs there was no way to get the version
749 number. From C code you can use ELF weak linking tricks to find out if
750 this symbol exists (if it doesn't, then it's an earlier version).
752 The call returns a structure with four elements. The first
753 three (C<major>, C<minor> and C<release>) are numbers and
754 correspond to the usual version triplet. The fourth element
755 (C<extra>) is a string and is normally empty, but may be
756 used for distro-specific information.
758 To construct the original version string:
759 C<$major.$minor.$release$extra>
761 I<Note:> Don't use this call to test for availability
762 of features. Distro backports makes this unreliable.");
764 ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
765 [InitNone, Always, TestOutputTrue (
766 [["set_selinux"; "true"];
768 "set SELinux enabled or disabled at appliance boot",
770 This sets the selinux flag that is passed to the appliance
771 at boot time. The default is C<selinux=0> (disabled).
773 Note that if SELinux is enabled, it is always in
774 Permissive mode (C<enforcing=0>).
776 For more information on the architecture of libguestfs,
777 see L<guestfs(3)>.");
779 ("get_selinux", (RBool "selinux", []), -1, [],
781 "get SELinux enabled flag",
783 This returns the current setting of the selinux flag which
784 is passed to the appliance at boot time. See C<guestfs_set_selinux>.
786 For more information on the architecture of libguestfs,
787 see L<guestfs(3)>.");
791 (* daemon_functions are any functions which cause some action
792 * to take place in the daemon.
795 let daemon_functions = [
796 ("mount", (RErr, [String "device"; String "mountpoint"]), 1, [],
797 [InitEmpty, Always, TestOutput (
798 [["sfdiskM"; "/dev/sda"; ","];
799 ["mkfs"; "ext2"; "/dev/sda1"];
800 ["mount"; "/dev/sda1"; "/"];
801 ["write_file"; "/new"; "new file contents"; "0"];
802 ["cat"; "/new"]], "new file contents")],
803 "mount a guest disk at a position in the filesystem",
805 Mount a guest disk at a position in the filesystem. Block devices
806 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
807 the guest. If those block devices contain partitions, they will have
808 the usual names (eg. C</dev/sda1>). Also LVM C</dev/VG/LV>-style
811 The rules are the same as for L<mount(2)>: A filesystem must
812 first be mounted on C</> before others can be mounted. Other
813 filesystems can only be mounted on directories which already
816 The mounted filesystem is writable, if we have sufficient permissions
817 on the underlying device.
819 The filesystem options C<sync> and C<noatime> are set with this
820 call, in order to improve reliability.");
822 ("sync", (RErr, []), 2, [],
823 [ InitEmpty, Always, TestRun [["sync"]]],
824 "sync disks, writes are flushed through to the disk image",
826 This syncs the disk, so that any writes are flushed through to the
827 underlying disk image.
829 You should always call this if you have modified a disk image, before
830 closing the handle.");
832 ("touch", (RErr, [String "path"]), 3, [],
833 [InitBasicFS, Always, TestOutputTrue (
835 ["exists"; "/new"]])],
836 "update file timestamps or create a new file",
838 Touch acts like the L<touch(1)> command. It can be used to
839 update the timestamps on a file, or, if the file does not exist,
840 to create a new zero-length file.");
842 ("cat", (RString "content", [String "path"]), 4, [ProtocolLimitWarning],
843 [InitSquashFS, Always, TestOutput (
844 [["cat"; "/known-2"]], "abcdef\n")],
845 "list the contents of a file",
847 Return the contents of the file named C<path>.
849 Note that this function cannot correctly handle binary files
850 (specifically, files containing C<\\0> character which is treated
851 as end of string). For those you need to use the C<guestfs_read_file>
852 or C<guestfs_download> functions which have a more complex interface.");
854 ("ll", (RString "listing", [String "directory"]), 5, [],
855 [], (* XXX Tricky to test because it depends on the exact format
856 * of the 'ls -l' command, which changes between F10 and F11.
858 "list the files in a directory (long format)",
860 List the files in C<directory> (relative to the root directory,
861 there is no cwd) in the format of 'ls -la'.
863 This command is mostly useful for interactive sessions. It
864 is I<not> intended that you try to parse the output string.");
866 ("ls", (RStringList "listing", [String "directory"]), 6, [],
867 [InitBasicFS, Always, TestOutputList (
870 ["touch"; "/newest"];
871 ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
872 "list the files in a directory",
874 List the files in C<directory> (relative to the root directory,
875 there is no cwd). The '.' and '..' entries are not returned, but
876 hidden files are shown.
878 This command is mostly useful for interactive sessions. Programs
879 should probably use C<guestfs_readdir> instead.");
881 ("list_devices", (RStringList "devices", []), 7, [],
882 [InitEmpty, Always, TestOutputListOfDevices (
883 [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
884 "list the block devices",
886 List all the block devices.
888 The full block device names are returned, eg. C</dev/sda>");
890 ("list_partitions", (RStringList "partitions", []), 8, [],
891 [InitBasicFS, Always, TestOutputListOfDevices (
892 [["list_partitions"]], ["/dev/sda1"]);
893 InitEmpty, Always, TestOutputListOfDevices (
894 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
895 ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
896 "list the partitions",
898 List all the partitions detected on all block devices.
900 The full partition device names are returned, eg. C</dev/sda1>
902 This does not return logical volumes. For that you will need to
903 call C<guestfs_lvs>.");
905 ("pvs", (RStringList "physvols", []), 9, [],
906 [InitBasicFSonLVM, Always, TestOutputListOfDevices (
907 [["pvs"]], ["/dev/sda1"]);
908 InitEmpty, Always, TestOutputListOfDevices (
909 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
910 ["pvcreate"; "/dev/sda1"];
911 ["pvcreate"; "/dev/sda2"];
912 ["pvcreate"; "/dev/sda3"];
913 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
914 "list the LVM physical volumes (PVs)",
916 List all the physical volumes detected. This is the equivalent
917 of the L<pvs(8)> command.
919 This returns a list of just the device names that contain
920 PVs (eg. C</dev/sda2>).
922 See also C<guestfs_pvs_full>.");
924 ("vgs", (RStringList "volgroups", []), 10, [],
925 [InitBasicFSonLVM, Always, TestOutputList (
927 InitEmpty, Always, TestOutputList (
928 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
929 ["pvcreate"; "/dev/sda1"];
930 ["pvcreate"; "/dev/sda2"];
931 ["pvcreate"; "/dev/sda3"];
932 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
933 ["vgcreate"; "VG2"; "/dev/sda3"];
934 ["vgs"]], ["VG1"; "VG2"])],
935 "list the LVM volume groups (VGs)",
937 List all the volumes groups detected. This is the equivalent
938 of the L<vgs(8)> command.
940 This returns a list of just the volume group names that were
941 detected (eg. C<VolGroup00>).
943 See also C<guestfs_vgs_full>.");
945 ("lvs", (RStringList "logvols", []), 11, [],
946 [InitBasicFSonLVM, Always, TestOutputList (
947 [["lvs"]], ["/dev/VG/LV"]);
948 InitEmpty, Always, TestOutputList (
949 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
950 ["pvcreate"; "/dev/sda1"];
951 ["pvcreate"; "/dev/sda2"];
952 ["pvcreate"; "/dev/sda3"];
953 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
954 ["vgcreate"; "VG2"; "/dev/sda3"];
955 ["lvcreate"; "LV1"; "VG1"; "50"];
956 ["lvcreate"; "LV2"; "VG1"; "50"];
957 ["lvcreate"; "LV3"; "VG2"; "50"];
958 ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
959 "list the LVM logical volumes (LVs)",
961 List all the logical volumes detected. This is the equivalent
962 of the L<lvs(8)> command.
964 This returns a list of the logical volume device names
965 (eg. C</dev/VolGroup00/LogVol00>).
967 See also C<guestfs_lvs_full>.");
969 ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
970 [], (* XXX how to test? *)
971 "list the LVM physical volumes (PVs)",
973 List all the physical volumes detected. This is the equivalent
974 of the L<pvs(8)> command. The \"full\" version includes all fields.");
976 ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
977 [], (* XXX how to test? *)
978 "list the LVM volume groups (VGs)",
980 List all the volumes groups detected. This is the equivalent
981 of the L<vgs(8)> command. The \"full\" version includes all fields.");
983 ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
984 [], (* XXX how to test? *)
985 "list the LVM logical volumes (LVs)",
987 List all the logical volumes detected. This is the equivalent
988 of the L<lvs(8)> command. The \"full\" version includes all fields.");
990 ("read_lines", (RStringList "lines", [String "path"]), 15, [],
991 [InitSquashFS, Always, TestOutputList (
992 [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
993 InitSquashFS, Always, TestOutputList (
994 [["read_lines"; "/empty"]], [])],
995 "read file as lines",
997 Return the contents of the file named C<path>.
999 The file contents are returned as a list of lines. Trailing
1000 C<LF> and C<CRLF> character sequences are I<not> returned.
1002 Note that this function cannot correctly handle binary files
1003 (specifically, files containing C<\\0> character which is treated
1004 as end of line). For those you need to use the C<guestfs_read_file>
1005 function which has a more complex interface.");
1007 ("aug_init", (RErr, [String "root"; Int "flags"]), 16, [],
1008 [], (* XXX Augeas code needs tests. *)
1009 "create a new Augeas handle",
1011 Create a new Augeas handle for editing configuration files.
1012 If there was any previous Augeas handle associated with this
1013 guestfs session, then it is closed.
1015 You must call this before using any other C<guestfs_aug_*>
1018 C<root> is the filesystem root. C<root> must not be NULL,
1021 The flags are the same as the flags defined in
1022 E<lt>augeas.hE<gt>, the logical I<or> of the following
1027 =item C<AUG_SAVE_BACKUP> = 1
1029 Keep the original file with a C<.augsave> extension.
1031 =item C<AUG_SAVE_NEWFILE> = 2
1033 Save changes into a file with extension C<.augnew>, and
1034 do not overwrite original. Overrides C<AUG_SAVE_BACKUP>.
1036 =item C<AUG_TYPE_CHECK> = 4
1038 Typecheck lenses (can be expensive).
1040 =item C<AUG_NO_STDINC> = 8
1042 Do not use standard load path for modules.
1044 =item C<AUG_SAVE_NOOP> = 16
1046 Make save a no-op, just record what would have been changed.
1048 =item C<AUG_NO_LOAD> = 32
1050 Do not load the tree in C<guestfs_aug_init>.
1054 To close the handle, you can call C<guestfs_aug_close>.
1056 To find out more about Augeas, see L<http://augeas.net/>.");
1058 ("aug_close", (RErr, []), 26, [],
1059 [], (* XXX Augeas code needs tests. *)
1060 "close the current Augeas handle",
1062 Close the current Augeas handle and free up any resources
1063 used by it. After calling this, you have to call
1064 C<guestfs_aug_init> again before you can use any other
1065 Augeas functions.");
1067 ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1068 [], (* XXX Augeas code needs tests. *)
1069 "define an Augeas variable",
1071 Defines an Augeas variable C<name> whose value is the result
1072 of evaluating C<expr>. If C<expr> is NULL, then C<name> is
1075 On success this returns the number of nodes in C<expr>, or
1076 C<0> if C<expr> evaluates to something which is not a nodeset.");
1078 ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1079 [], (* XXX Augeas code needs tests. *)
1080 "define an Augeas node",
1082 Defines a variable C<name> whose value is the result of
1085 If C<expr> evaluates to an empty nodeset, a node is created,
1086 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1087 C<name> will be the nodeset containing that single node.
1089 On success this returns a pair containing the
1090 number of nodes in the nodeset, and a boolean flag
1091 if a node was created.");
1093 ("aug_get", (RString "val", [String "path"]), 19, [],
1094 [], (* XXX Augeas code needs tests. *)
1095 "look up the value of an Augeas path",
1097 Look up the value associated with C<path>. If C<path>
1098 matches exactly one node, the C<value> is returned.");
1100 ("aug_set", (RErr, [String "path"; String "val"]), 20, [],
1101 [], (* XXX Augeas code needs tests. *)
1102 "set Augeas path to value",
1104 Set the value associated with C<path> to C<value>.");
1106 ("aug_insert", (RErr, [String "path"; String "label"; Bool "before"]), 21, [],
1107 [], (* XXX Augeas code needs tests. *)
1108 "insert a sibling Augeas node",
1110 Create a new sibling C<label> for C<path>, inserting it into
1111 the tree before or after C<path> (depending on the boolean
1114 C<path> must match exactly one existing node in the tree, and
1115 C<label> must be a label, ie. not contain C</>, C<*> or end
1116 with a bracketed index C<[N]>.");
1118 ("aug_rm", (RInt "nrnodes", [String "path"]), 22, [],
1119 [], (* XXX Augeas code needs tests. *)
1120 "remove an Augeas path",
1122 Remove C<path> and all of its children.
1124 On success this returns the number of entries which were removed.");
1126 ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1127 [], (* XXX Augeas code needs tests. *)
1130 Move the node C<src> to C<dest>. C<src> must match exactly
1131 one node. C<dest> is overwritten if it exists.");
1133 ("aug_match", (RStringList "matches", [String "path"]), 24, [],
1134 [], (* XXX Augeas code needs tests. *)
1135 "return Augeas nodes which match path",
1137 Returns a list of paths which match the path expression C<path>.
1138 The returned paths are sufficiently qualified so that they match
1139 exactly one node in the current tree.");
1141 ("aug_save", (RErr, []), 25, [],
1142 [], (* XXX Augeas code needs tests. *)
1143 "write all pending Augeas changes to disk",
1145 This writes all pending changes to disk.
1147 The flags which were passed to C<guestfs_aug_init> affect exactly
1148 how files are saved.");
1150 ("aug_load", (RErr, []), 27, [],
1151 [], (* XXX Augeas code needs tests. *)
1152 "load files into the tree",
1154 Load files into the tree.
1156 See C<aug_load> in the Augeas documentation for the full gory
1159 ("aug_ls", (RStringList "matches", [String "path"]), 28, [],
1160 [], (* XXX Augeas code needs tests. *)
1161 "list Augeas nodes under a path",
1163 This is just a shortcut for listing C<guestfs_aug_match>
1164 C<path/*> and sorting the resulting nodes into alphabetical order.");
1166 ("rm", (RErr, [String "path"]), 29, [],
1167 [InitBasicFS, Always, TestRun
1170 InitBasicFS, Always, TestLastFail
1172 InitBasicFS, Always, TestLastFail
1177 Remove the single file C<path>.");
1179 ("rmdir", (RErr, [String "path"]), 30, [],
1180 [InitBasicFS, Always, TestRun
1183 InitBasicFS, Always, TestLastFail
1184 [["rmdir"; "/new"]];
1185 InitBasicFS, Always, TestLastFail
1187 ["rmdir"; "/new"]]],
1188 "remove a directory",
1190 Remove the single directory C<path>.");
1192 ("rm_rf", (RErr, [String "path"]), 31, [],
1193 [InitBasicFS, Always, TestOutputFalse
1195 ["mkdir"; "/new/foo"];
1196 ["touch"; "/new/foo/bar"];
1198 ["exists"; "/new"]]],
1199 "remove a file or directory recursively",
1201 Remove the file or directory C<path>, recursively removing the
1202 contents if its a directory. This is like the C<rm -rf> shell
1205 ("mkdir", (RErr, [String "path"]), 32, [],
1206 [InitBasicFS, Always, TestOutputTrue
1208 ["is_dir"; "/new"]];
1209 InitBasicFS, Always, TestLastFail
1210 [["mkdir"; "/new/foo/bar"]]],
1211 "create a directory",
1213 Create a directory named C<path>.");
1215 ("mkdir_p", (RErr, [String "path"]), 33, [],
1216 [InitBasicFS, Always, TestOutputTrue
1217 [["mkdir_p"; "/new/foo/bar"];
1218 ["is_dir"; "/new/foo/bar"]];
1219 InitBasicFS, Always, TestOutputTrue
1220 [["mkdir_p"; "/new/foo/bar"];
1221 ["is_dir"; "/new/foo"]];
1222 InitBasicFS, Always, TestOutputTrue
1223 [["mkdir_p"; "/new/foo/bar"];
1224 ["is_dir"; "/new"]];
1225 (* Regression tests for RHBZ#503133: *)
1226 InitBasicFS, Always, TestRun
1228 ["mkdir_p"; "/new"]];
1229 InitBasicFS, Always, TestLastFail
1231 ["mkdir_p"; "/new"]]],
1232 "create a directory and parents",
1234 Create a directory named C<path>, creating any parent directories
1235 as necessary. This is like the C<mkdir -p> shell command.");
1237 ("chmod", (RErr, [Int "mode"; String "path"]), 34, [],
1238 [], (* XXX Need stat command to test *)
1241 Change the mode (permissions) of C<path> to C<mode>. Only
1242 numeric modes are supported.");
1244 ("chown", (RErr, [Int "owner"; Int "group"; String "path"]), 35, [],
1245 [], (* XXX Need stat command to test *)
1246 "change file owner and group",
1248 Change the file owner to C<owner> and group to C<group>.
1250 Only numeric uid and gid are supported. If you want to use
1251 names, you will need to locate and parse the password file
1252 yourself (Augeas support makes this relatively easy).");
1254 ("exists", (RBool "existsflag", [String "path"]), 36, [],
1255 [InitSquashFS, Always, TestOutputTrue (
1256 [["exists"; "/empty"]]);
1257 InitSquashFS, Always, TestOutputTrue (
1258 [["exists"; "/directory"]])],
1259 "test if file or directory exists",
1261 This returns C<true> if and only if there is a file, directory
1262 (or anything) with the given C<path> name.
1264 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1266 ("is_file", (RBool "fileflag", [String "path"]), 37, [],
1267 [InitSquashFS, Always, TestOutputTrue (
1268 [["is_file"; "/known-1"]]);
1269 InitSquashFS, Always, TestOutputFalse (
1270 [["is_file"; "/directory"]])],
1271 "test if file exists",
1273 This returns C<true> if and only if there is a file
1274 with the given C<path> name. Note that it returns false for
1275 other objects like directories.
1277 See also C<guestfs_stat>.");
1279 ("is_dir", (RBool "dirflag", [String "path"]), 38, [],
1280 [InitSquashFS, Always, TestOutputFalse (
1281 [["is_dir"; "/known-3"]]);
1282 InitSquashFS, Always, TestOutputTrue (
1283 [["is_dir"; "/directory"]])],
1284 "test if file exists",
1286 This returns C<true> if and only if there is a directory
1287 with the given C<path> name. Note that it returns false for
1288 other objects like files.
1290 See also C<guestfs_stat>.");
1292 ("pvcreate", (RErr, [String "device"]), 39, [],
1293 [InitEmpty, Always, TestOutputListOfDevices (
1294 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1295 ["pvcreate"; "/dev/sda1"];
1296 ["pvcreate"; "/dev/sda2"];
1297 ["pvcreate"; "/dev/sda3"];
1298 ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1299 "create an LVM physical volume",
1301 This creates an LVM physical volume on the named C<device>,
1302 where C<device> should usually be a partition name such
1305 ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
1306 [InitEmpty, Always, TestOutputList (
1307 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1308 ["pvcreate"; "/dev/sda1"];
1309 ["pvcreate"; "/dev/sda2"];
1310 ["pvcreate"; "/dev/sda3"];
1311 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1312 ["vgcreate"; "VG2"; "/dev/sda3"];
1313 ["vgs"]], ["VG1"; "VG2"])],
1314 "create an LVM volume group",
1316 This creates an LVM volume group called C<volgroup>
1317 from the non-empty list of physical volumes C<physvols>.");
1319 ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1320 [InitEmpty, Always, TestOutputList (
1321 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1322 ["pvcreate"; "/dev/sda1"];
1323 ["pvcreate"; "/dev/sda2"];
1324 ["pvcreate"; "/dev/sda3"];
1325 ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1326 ["vgcreate"; "VG2"; "/dev/sda3"];
1327 ["lvcreate"; "LV1"; "VG1"; "50"];
1328 ["lvcreate"; "LV2"; "VG1"; "50"];
1329 ["lvcreate"; "LV3"; "VG2"; "50"];
1330 ["lvcreate"; "LV4"; "VG2"; "50"];
1331 ["lvcreate"; "LV5"; "VG2"; "50"];
1333 ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1334 "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1335 "create an LVM volume group",
1337 This creates an LVM volume group called C<logvol>
1338 on the volume group C<volgroup>, with C<size> megabytes.");
1340 ("mkfs", (RErr, [String "fstype"; String "device"]), 42, [],
1341 [InitEmpty, Always, TestOutput (
1342 [["sfdiskM"; "/dev/sda"; ","];
1343 ["mkfs"; "ext2"; "/dev/sda1"];
1344 ["mount"; "/dev/sda1"; "/"];
1345 ["write_file"; "/new"; "new file contents"; "0"];
1346 ["cat"; "/new"]], "new file contents")],
1347 "make a filesystem",
1349 This creates a filesystem on C<device> (usually a partition
1350 or LVM logical volume). The filesystem type is C<fstype>, for
1353 ("sfdisk", (RErr, [String "device";
1354 Int "cyls"; Int "heads"; Int "sectors";
1355 StringList "lines"]), 43, [DangerWillRobinson],
1357 "create partitions on a block device",
1359 This is a direct interface to the L<sfdisk(8)> program for creating
1360 partitions on block devices.
1362 C<device> should be a block device, for example C</dev/sda>.
1364 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1365 and sectors on the device, which are passed directly to sfdisk as
1366 the I<-C>, I<-H> and I<-S> parameters. If you pass C<0> for any
1367 of these, then the corresponding parameter is omitted. Usually for
1368 'large' disks, you can just pass C<0> for these, but for small
1369 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1370 out the right geometry and you will need to tell it.
1372 C<lines> is a list of lines that we feed to C<sfdisk>. For more
1373 information refer to the L<sfdisk(8)> manpage.
1375 To create a single partition occupying the whole disk, you would
1376 pass C<lines> as a single element list, when the single element being
1377 the string C<,> (comma).
1379 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1381 ("write_file", (RErr, [String "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1382 [InitBasicFS, Always, TestOutput (
1383 [["write_file"; "/new"; "new file contents"; "0"];
1384 ["cat"; "/new"]], "new file contents");
1385 InitBasicFS, Always, TestOutput (
1386 [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1387 ["cat"; "/new"]], "\nnew file contents\n");
1388 InitBasicFS, Always, TestOutput (
1389 [["write_file"; "/new"; "\n\n"; "0"];
1390 ["cat"; "/new"]], "\n\n");
1391 InitBasicFS, Always, TestOutput (
1392 [["write_file"; "/new"; ""; "0"];
1393 ["cat"; "/new"]], "");
1394 InitBasicFS, Always, TestOutput (
1395 [["write_file"; "/new"; "\n\n\n"; "0"];
1396 ["cat"; "/new"]], "\n\n\n");
1397 InitBasicFS, Always, TestOutput (
1398 [["write_file"; "/new"; "\n"; "0"];
1399 ["cat"; "/new"]], "\n")],
1402 This call creates a file called C<path>. The contents of the
1403 file is the string C<content> (which can contain any 8 bit data),
1404 with length C<size>.
1406 As a special case, if C<size> is C<0>
1407 then the length is calculated using C<strlen> (so in this case
1408 the content cannot contain embedded ASCII NULs).
1410 I<NB.> Owing to a bug, writing content containing ASCII NUL
1411 characters does I<not> work, even if the length is specified.
1412 We hope to resolve this bug in a future version. In the meantime
1413 use C<guestfs_upload>.");
1415 ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1416 [InitEmpty, Always, TestOutputListOfDevices (
1417 [["sfdiskM"; "/dev/sda"; ","];
1418 ["mkfs"; "ext2"; "/dev/sda1"];
1419 ["mount"; "/dev/sda1"; "/"];
1420 ["mounts"]], ["/dev/sda1"]);
1421 InitEmpty, Always, TestOutputList (
1422 [["sfdiskM"; "/dev/sda"; ","];
1423 ["mkfs"; "ext2"; "/dev/sda1"];
1424 ["mount"; "/dev/sda1"; "/"];
1427 "unmount a filesystem",
1429 This unmounts the given filesystem. The filesystem may be
1430 specified either by its mountpoint (path) or the device which
1431 contains the filesystem.");
1433 ("mounts", (RStringList "devices", []), 46, [],
1434 [InitBasicFS, Always, TestOutputListOfDevices (
1435 [["mounts"]], ["/dev/sda1"])],
1436 "show mounted filesystems",
1438 This returns the list of currently mounted filesystems. It returns
1439 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1441 Some internal mounts are not shown.
1443 See also: C<guestfs_mountpoints>");
1445 ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1446 [InitBasicFS, Always, TestOutputList (
1449 (* check that umount_all can unmount nested mounts correctly: *)
1450 InitEmpty, Always, TestOutputList (
1451 [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1452 ["mkfs"; "ext2"; "/dev/sda1"];
1453 ["mkfs"; "ext2"; "/dev/sda2"];
1454 ["mkfs"; "ext2"; "/dev/sda3"];
1455 ["mount"; "/dev/sda1"; "/"];
1457 ["mount"; "/dev/sda2"; "/mp1"];
1458 ["mkdir"; "/mp1/mp2"];
1459 ["mount"; "/dev/sda3"; "/mp1/mp2"];
1460 ["mkdir"; "/mp1/mp2/mp3"];
1463 "unmount all filesystems",
1465 This unmounts all mounted filesystems.
1467 Some internal mounts are not unmounted by this call.");
1469 ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1471 "remove all LVM LVs, VGs and PVs",
1473 This command removes all LVM logical volumes, volume groups
1474 and physical volumes.");
1476 ("file", (RString "description", [String "path"]), 49, [],
1477 [InitSquashFS, Always, TestOutput (
1478 [["file"; "/empty"]], "empty");
1479 InitSquashFS, Always, TestOutput (
1480 [["file"; "/known-1"]], "ASCII text");
1481 InitSquashFS, Always, TestLastFail (
1482 [["file"; "/notexists"]])],
1483 "determine file type",
1485 This call uses the standard L<file(1)> command to determine
1486 the type or contents of the file. This also works on devices,
1487 for example to find out whether a partition contains a filesystem.
1489 This call will also transparently look inside various types
1492 The exact command which runs is C<file -zbsL path>. Note in
1493 particular that the filename is not prepended to the output
1494 (the C<-b> option).");
1496 ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1497 [InitBasicFS, Always, TestOutput (
1498 [["upload"; "test-command"; "/test-command"];
1499 ["chmod"; "0o755"; "/test-command"];
1500 ["command"; "/test-command 1"]], "Result1");
1501 InitBasicFS, Always, TestOutput (
1502 [["upload"; "test-command"; "/test-command"];
1503 ["chmod"; "0o755"; "/test-command"];
1504 ["command"; "/test-command 2"]], "Result2\n");
1505 InitBasicFS, Always, TestOutput (
1506 [["upload"; "test-command"; "/test-command"];
1507 ["chmod"; "0o755"; "/test-command"];
1508 ["command"; "/test-command 3"]], "\nResult3");
1509 InitBasicFS, Always, TestOutput (
1510 [["upload"; "test-command"; "/test-command"];
1511 ["chmod"; "0o755"; "/test-command"];
1512 ["command"; "/test-command 4"]], "\nResult4\n");
1513 InitBasicFS, Always, TestOutput (
1514 [["upload"; "test-command"; "/test-command"];
1515 ["chmod"; "0o755"; "/test-command"];
1516 ["command"; "/test-command 5"]], "\nResult5\n\n");
1517 InitBasicFS, Always, TestOutput (
1518 [["upload"; "test-command"; "/test-command"];
1519 ["chmod"; "0o755"; "/test-command"];
1520 ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1521 InitBasicFS, Always, TestOutput (
1522 [["upload"; "test-command"; "/test-command"];
1523 ["chmod"; "0o755"; "/test-command"];
1524 ["command"; "/test-command 7"]], "");
1525 InitBasicFS, Always, TestOutput (
1526 [["upload"; "test-command"; "/test-command"];
1527 ["chmod"; "0o755"; "/test-command"];
1528 ["command"; "/test-command 8"]], "\n");
1529 InitBasicFS, Always, TestOutput (
1530 [["upload"; "test-command"; "/test-command"];
1531 ["chmod"; "0o755"; "/test-command"];
1532 ["command"; "/test-command 9"]], "\n\n");
1533 InitBasicFS, Always, TestOutput (
1534 [["upload"; "test-command"; "/test-command"];
1535 ["chmod"; "0o755"; "/test-command"];
1536 ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1537 InitBasicFS, Always, TestOutput (
1538 [["upload"; "test-command"; "/test-command"];
1539 ["chmod"; "0o755"; "/test-command"];
1540 ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1541 InitBasicFS, Always, TestLastFail (
1542 [["upload"; "test-command"; "/test-command"];
1543 ["chmod"; "0o755"; "/test-command"];
1544 ["command"; "/test-command"]])],
1545 "run a command from the guest filesystem",
1547 This call runs a command from the guest filesystem. The
1548 filesystem must be mounted, and must contain a compatible
1549 operating system (ie. something Linux, with the same
1550 or compatible processor architecture).
1552 The single parameter is an argv-style list of arguments.
1553 The first element is the name of the program to run.
1554 Subsequent elements are parameters. The list must be
1555 non-empty (ie. must contain a program name). Note that
1556 the command runs directly, and is I<not> invoked via
1557 the shell (see C<guestfs_sh>).
1559 The return value is anything printed to I<stdout> by
1562 If the command returns a non-zero exit status, then
1563 this function returns an error message. The error message
1564 string is the content of I<stderr> from the command.
1566 The C<$PATH> environment variable will contain at least
1567 C</usr/bin> and C</bin>. If you require a program from
1568 another location, you should provide the full path in the
1571 Shared libraries and data files required by the program
1572 must be available on filesystems which are mounted in the
1573 correct places. It is the caller's responsibility to ensure
1574 all filesystems that are needed are mounted at the right
1577 ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1578 [InitBasicFS, Always, TestOutputList (
1579 [["upload"; "test-command"; "/test-command"];
1580 ["chmod"; "0o755"; "/test-command"];
1581 ["command_lines"; "/test-command 1"]], ["Result1"]);
1582 InitBasicFS, Always, TestOutputList (
1583 [["upload"; "test-command"; "/test-command"];
1584 ["chmod"; "0o755"; "/test-command"];
1585 ["command_lines"; "/test-command 2"]], ["Result2"]);
1586 InitBasicFS, Always, TestOutputList (
1587 [["upload"; "test-command"; "/test-command"];
1588 ["chmod"; "0o755"; "/test-command"];
1589 ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1590 InitBasicFS, Always, TestOutputList (
1591 [["upload"; "test-command"; "/test-command"];
1592 ["chmod"; "0o755"; "/test-command"];
1593 ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1594 InitBasicFS, Always, TestOutputList (
1595 [["upload"; "test-command"; "/test-command"];
1596 ["chmod"; "0o755"; "/test-command"];
1597 ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1598 InitBasicFS, Always, TestOutputList (
1599 [["upload"; "test-command"; "/test-command"];
1600 ["chmod"; "0o755"; "/test-command"];
1601 ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1602 InitBasicFS, Always, TestOutputList (
1603 [["upload"; "test-command"; "/test-command"];
1604 ["chmod"; "0o755"; "/test-command"];
1605 ["command_lines"; "/test-command 7"]], []);
1606 InitBasicFS, Always, TestOutputList (
1607 [["upload"; "test-command"; "/test-command"];
1608 ["chmod"; "0o755"; "/test-command"];
1609 ["command_lines"; "/test-command 8"]], [""]);
1610 InitBasicFS, Always, TestOutputList (
1611 [["upload"; "test-command"; "/test-command"];
1612 ["chmod"; "0o755"; "/test-command"];
1613 ["command_lines"; "/test-command 9"]], ["";""]);
1614 InitBasicFS, Always, TestOutputList (
1615 [["upload"; "test-command"; "/test-command"];
1616 ["chmod"; "0o755"; "/test-command"];
1617 ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1618 InitBasicFS, Always, TestOutputList (
1619 [["upload"; "test-command"; "/test-command"];
1620 ["chmod"; "0o755"; "/test-command"];
1621 ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1622 "run a command, returning lines",
1624 This is the same as C<guestfs_command>, but splits the
1625 result into a list of lines.
1627 See also: C<guestfs_sh_lines>");
1629 ("stat", (RStruct ("statbuf", "stat"), [String "path"]), 52, [],
1630 [InitSquashFS, Always, TestOutputStruct (
1631 [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1632 "get file information",
1634 Returns file information for the given C<path>.
1636 This is the same as the C<stat(2)> system call.");
1638 ("lstat", (RStruct ("statbuf", "stat"), [String "path"]), 53, [],
1639 [InitSquashFS, Always, TestOutputStruct (
1640 [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1641 "get file information for a symbolic link",
1643 Returns file information for the given C<path>.
1645 This is the same as C<guestfs_stat> except that if C<path>
1646 is a symbolic link, then the link is stat-ed, not the file it
1649 This is the same as the C<lstat(2)> system call.");
1651 ("statvfs", (RStruct ("statbuf", "statvfs"), [String "path"]), 54, [],
1652 [InitSquashFS, Always, TestOutputStruct (
1653 [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
1654 "get file system statistics",
1656 Returns file system statistics for any mounted file system.
1657 C<path> should be a file or directory in the mounted file system
1658 (typically it is the mount point itself, but it doesn't need to be).
1660 This is the same as the C<statvfs(2)> system call.");
1662 ("tune2fs_l", (RHashtable "superblock", [String "device"]), 55, [],
1664 "get ext2/ext3/ext4 superblock details",
1666 This returns the contents of the ext2, ext3 or ext4 filesystem
1667 superblock on C<device>.
1669 It is the same as running C<tune2fs -l device>. See L<tune2fs(8)>
1670 manpage for more details. The list of fields returned isn't
1671 clearly defined, and depends on both the version of C<tune2fs>
1672 that libguestfs was built against, and the filesystem itself.");
1674 ("blockdev_setro", (RErr, [String "device"]), 56, [],
1675 [InitEmpty, Always, TestOutputTrue (
1676 [["blockdev_setro"; "/dev/sda"];
1677 ["blockdev_getro"; "/dev/sda"]])],
1678 "set block device to read-only",
1680 Sets the block device named C<device> to read-only.
1682 This uses the L<blockdev(8)> command.");
1684 ("blockdev_setrw", (RErr, [String "device"]), 57, [],
1685 [InitEmpty, Always, TestOutputFalse (
1686 [["blockdev_setrw"; "/dev/sda"];
1687 ["blockdev_getro"; "/dev/sda"]])],
1688 "set block device to read-write",
1690 Sets the block device named C<device> to read-write.
1692 This uses the L<blockdev(8)> command.");
1694 ("blockdev_getro", (RBool "ro", [String "device"]), 58, [],
1695 [InitEmpty, Always, TestOutputTrue (
1696 [["blockdev_setro"; "/dev/sda"];
1697 ["blockdev_getro"; "/dev/sda"]])],
1698 "is block device set to read-only",
1700 Returns a boolean indicating if the block device is read-only
1701 (true if read-only, false if not).
1703 This uses the L<blockdev(8)> command.");
1705 ("blockdev_getss", (RInt "sectorsize", [String "device"]), 59, [],
1706 [InitEmpty, Always, TestOutputInt (
1707 [["blockdev_getss"; "/dev/sda"]], 512)],
1708 "get sectorsize of block device",
1710 This returns the size of sectors on a block device.
1711 Usually 512, but can be larger for modern devices.
1713 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1716 This uses the L<blockdev(8)> command.");
1718 ("blockdev_getbsz", (RInt "blocksize", [String "device"]), 60, [],
1719 [InitEmpty, Always, TestOutputInt (
1720 [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1721 "get blocksize of block device",
1723 This returns the block size of a device.
1725 (Note this is different from both I<size in blocks> and
1726 I<filesystem block size>).
1728 This uses the L<blockdev(8)> command.");
1730 ("blockdev_setbsz", (RErr, [String "device"; Int "blocksize"]), 61, [],
1732 "set blocksize of block device",
1734 This sets the block size of a device.
1736 (Note this is different from both I<size in blocks> and
1737 I<filesystem block size>).
1739 This uses the L<blockdev(8)> command.");
1741 ("blockdev_getsz", (RInt64 "sizeinsectors", [String "device"]), 62, [],
1742 [InitEmpty, Always, TestOutputInt (
1743 [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1744 "get total size of device in 512-byte sectors",
1746 This returns the size of the device in units of 512-byte sectors
1747 (even if the sectorsize isn't 512 bytes ... weird).
1749 See also C<guestfs_blockdev_getss> for the real sector size of
1750 the device, and C<guestfs_blockdev_getsize64> for the more
1751 useful I<size in bytes>.
1753 This uses the L<blockdev(8)> command.");
1755 ("blockdev_getsize64", (RInt64 "sizeinbytes", [String "device"]), 63, [],
1756 [InitEmpty, Always, TestOutputInt (
1757 [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1758 "get total size of device in bytes",
1760 This returns the size of the device in bytes.
1762 See also C<guestfs_blockdev_getsz>.
1764 This uses the L<blockdev(8)> command.");
1766 ("blockdev_flushbufs", (RErr, [String "device"]), 64, [],
1767 [InitEmpty, Always, TestRun
1768 [["blockdev_flushbufs"; "/dev/sda"]]],
1769 "flush device buffers",
1771 This tells the kernel to flush internal buffers associated
1774 This uses the L<blockdev(8)> command.");
1776 ("blockdev_rereadpt", (RErr, [String "device"]), 65, [],
1777 [InitEmpty, Always, TestRun
1778 [["blockdev_rereadpt"; "/dev/sda"]]],
1779 "reread partition table",
1781 Reread the partition table on C<device>.
1783 This uses the L<blockdev(8)> command.");
1785 ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1786 [InitBasicFS, Always, TestOutput (
1787 (* Pick a file from cwd which isn't likely to change. *)
1788 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1789 ["checksum"; "md5"; "/COPYING.LIB"]],
1790 Digest.to_hex (Digest.file "COPYING.LIB"))],
1791 "upload a file from the local machine",
1793 Upload local file C<filename> to C<remotefilename> on the
1796 C<filename> can also be a named pipe.
1798 See also C<guestfs_download>.");
1800 ("download", (RErr, [String "remotefilename"; FileOut "filename"]), 67, [],
1801 [InitBasicFS, Always, TestOutput (
1802 (* Pick a file from cwd which isn't likely to change. *)
1803 [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1804 ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1805 ["upload"; "testdownload.tmp"; "/upload"];
1806 ["checksum"; "md5"; "/upload"]],
1807 Digest.to_hex (Digest.file "COPYING.LIB"))],
1808 "download a file to the local machine",
1810 Download file C<remotefilename> and save it as C<filename>
1811 on the local machine.
1813 C<filename> can also be a named pipe.
1815 See also C<guestfs_upload>, C<guestfs_cat>.");
1817 ("checksum", (RString "checksum", [String "csumtype"; String "path"]), 68, [],
1818 [InitSquashFS, Always, TestOutput (
1819 [["checksum"; "crc"; "/known-3"]], "2891671662");
1820 InitSquashFS, Always, TestLastFail (
1821 [["checksum"; "crc"; "/notexists"]]);
1822 InitSquashFS, Always, TestOutput (
1823 [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1824 InitSquashFS, Always, TestOutput (
1825 [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1826 InitSquashFS, Always, TestOutput (
1827 [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1828 InitSquashFS, Always, TestOutput (
1829 [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1830 InitSquashFS, Always, TestOutput (
1831 [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1832 InitSquashFS, Always, TestOutput (
1833 [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1834 "compute MD5, SHAx or CRC checksum of file",
1836 This call computes the MD5, SHAx or CRC checksum of the
1839 The type of checksum to compute is given by the C<csumtype>
1840 parameter which must have one of the following values:
1846 Compute the cyclic redundancy check (CRC) specified by POSIX
1847 for the C<cksum> command.
1851 Compute the MD5 hash (using the C<md5sum> program).
1855 Compute the SHA1 hash (using the C<sha1sum> program).
1859 Compute the SHA224 hash (using the C<sha224sum> program).
1863 Compute the SHA256 hash (using the C<sha256sum> program).
1867 Compute the SHA384 hash (using the C<sha384sum> program).
1871 Compute the SHA512 hash (using the C<sha512sum> program).
1875 The checksum is returned as a printable string.");
1877 ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1878 [InitBasicFS, Always, TestOutput (
1879 [["tar_in"; "../images/helloworld.tar"; "/"];
1880 ["cat"; "/hello"]], "hello\n")],
1881 "unpack tarfile to directory",
1883 This command uploads and unpacks local file C<tarfile> (an
1884 I<uncompressed> tar file) into C<directory>.
1886 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1888 ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1890 "pack directory into tarfile",
1892 This command packs the contents of C<directory> and downloads
1893 it to local file C<tarfile>.
1895 To download a compressed tarball, use C<guestfs_tgz_out>.");
1897 ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1898 [InitBasicFS, Always, TestOutput (
1899 [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1900 ["cat"; "/hello"]], "hello\n")],
1901 "unpack compressed tarball to directory",
1903 This command uploads and unpacks local file C<tarball> (a
1904 I<gzip compressed> tar file) into C<directory>.
1906 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1908 ("tgz_out", (RErr, [String "directory"; FileOut "tarball"]), 72, [],
1910 "pack directory into compressed tarball",
1912 This command packs the contents of C<directory> and downloads
1913 it to local file C<tarball>.
1915 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1917 ("mount_ro", (RErr, [String "device"; String "mountpoint"]), 73, [],
1918 [InitBasicFS, Always, TestLastFail (
1920 ["mount_ro"; "/dev/sda1"; "/"];
1921 ["touch"; "/new"]]);
1922 InitBasicFS, Always, TestOutput (
1923 [["write_file"; "/new"; "data"; "0"];
1925 ["mount_ro"; "/dev/sda1"; "/"];
1926 ["cat"; "/new"]], "data")],
1927 "mount a guest disk, read-only",
1929 This is the same as the C<guestfs_mount> command, but it
1930 mounts the filesystem with the read-only (I<-o ro>) flag.");
1932 ("mount_options", (RErr, [String "options"; String "device"; String "mountpoint"]), 74, [],
1934 "mount a guest disk with mount options",
1936 This is the same as the C<guestfs_mount> command, but it
1937 allows you to set the mount options as for the
1938 L<mount(8)> I<-o> flag.");
1940 ("mount_vfs", (RErr, [String "options"; String "vfstype"; String "device"; String "mountpoint"]), 75, [],
1942 "mount a guest disk with mount options and vfstype",
1944 This is the same as the C<guestfs_mount> command, but it
1945 allows you to set both the mount options and the vfstype
1946 as for the L<mount(8)> I<-o> and I<-t> flags.");
1948 ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1950 "debugging and internals",
1952 The C<guestfs_debug> command exposes some internals of
1953 C<guestfsd> (the guestfs daemon) that runs inside the
1956 There is no comprehensive help for this command. You have
1957 to look at the file C<daemon/debug.c> in the libguestfs source
1958 to find out what you can do.");
1960 ("lvremove", (RErr, [String "device"]), 77, [],
1961 [InitEmpty, Always, TestOutputList (
1962 [["sfdiskM"; "/dev/sda"; ","];
1963 ["pvcreate"; "/dev/sda1"];
1964 ["vgcreate"; "VG"; "/dev/sda1"];
1965 ["lvcreate"; "LV1"; "VG"; "50"];
1966 ["lvcreate"; "LV2"; "VG"; "50"];
1967 ["lvremove"; "/dev/VG/LV1"];
1968 ["lvs"]], ["/dev/VG/LV2"]);
1969 InitEmpty, Always, TestOutputList (
1970 [["sfdiskM"; "/dev/sda"; ","];
1971 ["pvcreate"; "/dev/sda1"];
1972 ["vgcreate"; "VG"; "/dev/sda1"];
1973 ["lvcreate"; "LV1"; "VG"; "50"];
1974 ["lvcreate"; "LV2"; "VG"; "50"];
1975 ["lvremove"; "/dev/VG"];
1977 InitEmpty, Always, TestOutputList (
1978 [["sfdiskM"; "/dev/sda"; ","];
1979 ["pvcreate"; "/dev/sda1"];
1980 ["vgcreate"; "VG"; "/dev/sda1"];
1981 ["lvcreate"; "LV1"; "VG"; "50"];
1982 ["lvcreate"; "LV2"; "VG"; "50"];
1983 ["lvremove"; "/dev/VG"];
1985 "remove an LVM logical volume",
1987 Remove an LVM logical volume C<device>, where C<device> is
1988 the path to the LV, such as C</dev/VG/LV>.
1990 You can also remove all LVs in a volume group by specifying
1991 the VG name, C</dev/VG>.");
1993 ("vgremove", (RErr, [String "vgname"]), 78, [],
1994 [InitEmpty, Always, TestOutputList (
1995 [["sfdiskM"; "/dev/sda"; ","];
1996 ["pvcreate"; "/dev/sda1"];
1997 ["vgcreate"; "VG"; "/dev/sda1"];
1998 ["lvcreate"; "LV1"; "VG"; "50"];
1999 ["lvcreate"; "LV2"; "VG"; "50"];
2002 InitEmpty, Always, TestOutputList (
2003 [["sfdiskM"; "/dev/sda"; ","];
2004 ["pvcreate"; "/dev/sda1"];
2005 ["vgcreate"; "VG"; "/dev/sda1"];
2006 ["lvcreate"; "LV1"; "VG"; "50"];
2007 ["lvcreate"; "LV2"; "VG"; "50"];
2010 "remove an LVM volume group",
2012 Remove an LVM volume group C<vgname>, (for example C<VG>).
2014 This also forcibly removes all logical volumes in the volume
2017 ("pvremove", (RErr, [String "device"]), 79, [],
2018 [InitEmpty, Always, TestOutputListOfDevices (
2019 [["sfdiskM"; "/dev/sda"; ","];
2020 ["pvcreate"; "/dev/sda1"];
2021 ["vgcreate"; "VG"; "/dev/sda1"];
2022 ["lvcreate"; "LV1"; "VG"; "50"];
2023 ["lvcreate"; "LV2"; "VG"; "50"];
2025 ["pvremove"; "/dev/sda1"];
2027 InitEmpty, Always, TestOutputListOfDevices (
2028 [["sfdiskM"; "/dev/sda"; ","];
2029 ["pvcreate"; "/dev/sda1"];
2030 ["vgcreate"; "VG"; "/dev/sda1"];
2031 ["lvcreate"; "LV1"; "VG"; "50"];
2032 ["lvcreate"; "LV2"; "VG"; "50"];
2034 ["pvremove"; "/dev/sda1"];
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 "remove an LVM physical volume",
2047 This wipes a physical volume C<device> so that LVM will no longer
2050 The implementation uses the C<pvremove> command which refuses to
2051 wipe physical volumes that contain any volume groups, so you have
2052 to remove those first.");
2054 ("set_e2label", (RErr, [String "device"; String "label"]), 80, [],
2055 [InitBasicFS, Always, TestOutput (
2056 [["set_e2label"; "/dev/sda1"; "testlabel"];
2057 ["get_e2label"; "/dev/sda1"]], "testlabel")],
2058 "set the ext2/3/4 filesystem label",
2060 This sets the ext2/3/4 filesystem label of the filesystem on
2061 C<device> to C<label>. Filesystem labels are limited to
2064 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2065 to return the existing label on a filesystem.");
2067 ("get_e2label", (RString "label", [String "device"]), 81, [],
2069 "get the ext2/3/4 filesystem label",
2071 This returns the ext2/3/4 filesystem label of the filesystem on
2074 ("set_e2uuid", (RErr, [String "device"; String "uuid"]), 82, [],
2075 [InitBasicFS, Always, TestOutput (
2076 [["set_e2uuid"; "/dev/sda1"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
2077 ["get_e2uuid"; "/dev/sda1"]], "a3a61220-882b-4f61-89f4-cf24dcc7297d");
2078 InitBasicFS, Always, TestOutput (
2079 [["set_e2uuid"; "/dev/sda1"; "clear"];
2080 ["get_e2uuid"; "/dev/sda1"]], "");
2081 (* We can't predict what UUIDs will be, so just check the commands run. *)
2082 InitBasicFS, Always, TestRun (
2083 [["set_e2uuid"; "/dev/sda1"; "random"]]);
2084 InitBasicFS, Always, TestRun (
2085 [["set_e2uuid"; "/dev/sda1"; "time"]])],
2086 "set the ext2/3/4 filesystem UUID",
2088 This sets the ext2/3/4 filesystem UUID of the filesystem on
2089 C<device> to C<uuid>. The format of the UUID and alternatives
2090 such as C<clear>, C<random> and C<time> are described in the
2091 L<tune2fs(8)> manpage.
2093 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2094 to return the existing UUID of a filesystem.");
2096 ("get_e2uuid", (RString "uuid", [String "device"]), 83, [],
2098 "get the ext2/3/4 filesystem UUID",
2100 This returns the ext2/3/4 filesystem UUID of the filesystem on
2103 ("fsck", (RInt "status", [String "fstype"; String "device"]), 84, [],
2104 [InitBasicFS, Always, TestOutputInt (
2105 [["umount"; "/dev/sda1"];
2106 ["fsck"; "ext2"; "/dev/sda1"]], 0);
2107 InitBasicFS, Always, TestOutputInt (
2108 [["umount"; "/dev/sda1"];
2109 ["zero"; "/dev/sda1"];
2110 ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2111 "run the filesystem checker",
2113 This runs the filesystem checker (fsck) on C<device> which
2114 should have filesystem type C<fstype>.
2116 The returned integer is the status. See L<fsck(8)> for the
2117 list of status codes from C<fsck>.
2125 Multiple status codes can be summed together.
2129 A non-zero return code can mean \"success\", for example if
2130 errors have been corrected on the filesystem.
2134 Checking or repairing NTFS volumes is not supported
2139 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2141 ("zero", (RErr, [String "device"]), 85, [],
2142 [InitBasicFS, Always, TestOutput (
2143 [["umount"; "/dev/sda1"];
2144 ["zero"; "/dev/sda1"];
2145 ["file"; "/dev/sda1"]], "data")],
2146 "write zeroes to the device",
2148 This command writes zeroes over the first few blocks of C<device>.
2150 How many blocks are zeroed isn't specified (but it's I<not> enough
2151 to securely wipe the device). It should be sufficient to remove
2152 any partition tables, filesystem superblocks and so on.
2154 See also: C<guestfs_scrub_device>.");
2156 ("grub_install", (RErr, [String "root"; String "device"]), 86, [],
2157 (* Test disabled because grub-install incompatible with virtio-blk driver.
2158 * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2160 [InitBasicFS, Disabled, TestOutputTrue (
2161 [["grub_install"; "/"; "/dev/sda1"];
2162 ["is_dir"; "/boot"]])],
2165 This command installs GRUB (the Grand Unified Bootloader) on
2166 C<device>, with the root directory being C<root>.");
2168 ("cp", (RErr, [String "src"; String "dest"]), 87, [],
2169 [InitBasicFS, Always, TestOutput (
2170 [["write_file"; "/old"; "file content"; "0"];
2171 ["cp"; "/old"; "/new"];
2172 ["cat"; "/new"]], "file content");
2173 InitBasicFS, Always, TestOutputTrue (
2174 [["write_file"; "/old"; "file content"; "0"];
2175 ["cp"; "/old"; "/new"];
2176 ["is_file"; "/old"]]);
2177 InitBasicFS, Always, TestOutput (
2178 [["write_file"; "/old"; "file content"; "0"];
2180 ["cp"; "/old"; "/dir/new"];
2181 ["cat"; "/dir/new"]], "file content")],
2184 This copies a file from C<src> to C<dest> where C<dest> is
2185 either a destination filename or destination directory.");
2187 ("cp_a", (RErr, [String "src"; String "dest"]), 88, [],
2188 [InitBasicFS, Always, TestOutput (
2189 [["mkdir"; "/olddir"];
2190 ["mkdir"; "/newdir"];
2191 ["write_file"; "/olddir/file"; "file content"; "0"];
2192 ["cp_a"; "/olddir"; "/newdir"];
2193 ["cat"; "/newdir/olddir/file"]], "file content")],
2194 "copy a file or directory recursively",
2196 This copies a file or directory from C<src> to C<dest>
2197 recursively using the C<cp -a> command.");
2199 ("mv", (RErr, [String "src"; String "dest"]), 89, [],
2200 [InitBasicFS, Always, TestOutput (
2201 [["write_file"; "/old"; "file content"; "0"];
2202 ["mv"; "/old"; "/new"];
2203 ["cat"; "/new"]], "file content");
2204 InitBasicFS, Always, TestOutputFalse (
2205 [["write_file"; "/old"; "file content"; "0"];
2206 ["mv"; "/old"; "/new"];
2207 ["is_file"; "/old"]])],
2210 This moves a file from C<src> to C<dest> where C<dest> is
2211 either a destination filename or destination directory.");
2213 ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2214 [InitEmpty, Always, TestRun (
2215 [["drop_caches"; "3"]])],
2216 "drop kernel page cache, dentries and inodes",
2218 This instructs the guest kernel to drop its page cache,
2219 and/or dentries and inode caches. The parameter C<whattodrop>
2220 tells the kernel what precisely to drop, see
2221 L<http://linux-mm.org/Drop_Caches>
2223 Setting C<whattodrop> to 3 should drop everything.
2225 This automatically calls L<sync(2)> before the operation,
2226 so that the maximum guest memory is freed.");
2228 ("dmesg", (RString "kmsgs", []), 91, [],
2229 [InitEmpty, Always, TestRun (
2231 "return kernel messages",
2233 This returns the kernel messages (C<dmesg> output) from
2234 the guest kernel. This is sometimes useful for extended
2235 debugging of problems.
2237 Another way to get the same information is to enable
2238 verbose messages with C<guestfs_set_verbose> or by setting
2239 the environment variable C<LIBGUESTFS_DEBUG=1> before
2240 running the program.");
2242 ("ping_daemon", (RErr, []), 92, [],
2243 [InitEmpty, Always, TestRun (
2244 [["ping_daemon"]])],
2245 "ping the guest daemon",
2247 This is a test probe into the guestfs daemon running inside
2248 the qemu subprocess. Calling this function checks that the
2249 daemon responds to the ping message, without affecting the daemon
2250 or attached block device(s) in any other way.");
2252 ("equal", (RBool "equality", [String "file1"; String "file2"]), 93, [],
2253 [InitBasicFS, Always, TestOutputTrue (
2254 [["write_file"; "/file1"; "contents of a file"; "0"];
2255 ["cp"; "/file1"; "/file2"];
2256 ["equal"; "/file1"; "/file2"]]);
2257 InitBasicFS, Always, TestOutputFalse (
2258 [["write_file"; "/file1"; "contents of a file"; "0"];
2259 ["write_file"; "/file2"; "contents of another file"; "0"];
2260 ["equal"; "/file1"; "/file2"]]);
2261 InitBasicFS, Always, TestLastFail (
2262 [["equal"; "/file1"; "/file2"]])],
2263 "test if two files have equal contents",
2265 This compares the two files C<file1> and C<file2> and returns
2266 true if their content is exactly equal, or false otherwise.
2268 The external L<cmp(1)> program is used for the comparison.");
2270 ("strings", (RStringList "stringsout", [String "path"]), 94, [ProtocolLimitWarning],
2271 [InitSquashFS, Always, TestOutputList (
2272 [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2273 InitSquashFS, Always, TestOutputList (
2274 [["strings"; "/empty"]], [])],
2275 "print the printable strings in a file",
2277 This runs the L<strings(1)> command on a file and returns
2278 the list of printable strings found.");
2280 ("strings_e", (RStringList "stringsout", [String "encoding"; String "path"]), 95, [ProtocolLimitWarning],
2281 [InitSquashFS, Always, TestOutputList (
2282 [["strings_e"; "b"; "/known-5"]], []);
2283 InitBasicFS, Disabled, TestOutputList (
2284 [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2285 ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2286 "print the printable strings in a file",
2288 This is like the C<guestfs_strings> command, but allows you to
2289 specify the encoding.
2291 See the L<strings(1)> manpage for the full list of encodings.
2293 Commonly useful encodings are C<l> (lower case L) which will
2294 show strings inside Windows/x86 files.
2296 The returned strings are transcoded to UTF-8.");
2298 ("hexdump", (RString "dump", [String "path"]), 96, [ProtocolLimitWarning],
2299 [InitSquashFS, Always, TestOutput (
2300 [["hexdump"; "/known-4"]], "00000000 61 62 63 0a 64 65 66 0a 67 68 69 |abc.def.ghi|\n0000000b\n");
2301 (* Test for RHBZ#501888c2 regression which caused large hexdump
2302 * commands to segfault.
2304 InitSquashFS, Always, TestRun (
2305 [["hexdump"; "/100krandom"]])],
2306 "dump a file in hexadecimal",
2308 This runs C<hexdump -C> on the given C<path>. The result is
2309 the human-readable, canonical hex dump of the file.");
2311 ("zerofree", (RErr, [String "device"]), 97, [],
2312 [InitNone, Always, TestOutput (
2313 [["sfdiskM"; "/dev/sda"; ","];
2314 ["mkfs"; "ext3"; "/dev/sda1"];
2315 ["mount"; "/dev/sda1"; "/"];
2316 ["write_file"; "/new"; "test file"; "0"];
2317 ["umount"; "/dev/sda1"];
2318 ["zerofree"; "/dev/sda1"];
2319 ["mount"; "/dev/sda1"; "/"];
2320 ["cat"; "/new"]], "test file")],
2321 "zero unused inodes and disk blocks on ext2/3 filesystem",
2323 This runs the I<zerofree> program on C<device>. This program
2324 claims to zero unused inodes and disk blocks on an ext2/3
2325 filesystem, thus making it possible to compress the filesystem
2328 You should B<not> run this program if the filesystem is
2331 It is possible that using this program can damage the filesystem
2332 or data on the filesystem.");
2334 ("pvresize", (RErr, [String "device"]), 98, [],
2336 "resize an LVM physical volume",
2338 This resizes (expands or shrinks) an existing LVM physical
2339 volume to match the new size of the underlying device.");
2341 ("sfdisk_N", (RErr, [String "device"; Int "partnum";
2342 Int "cyls"; Int "heads"; Int "sectors";
2343 String "line"]), 99, [DangerWillRobinson],
2345 "modify a single partition on a block device",
2347 This runs L<sfdisk(8)> option to modify just the single
2348 partition C<n> (note: C<n> counts from 1).
2350 For other parameters, see C<guestfs_sfdisk>. You should usually
2351 pass C<0> for the cyls/heads/sectors parameters.");
2353 ("sfdisk_l", (RString "partitions", [String "device"]), 100, [],
2355 "display the partition table",
2357 This displays the partition table on C<device>, in the
2358 human-readable output of the L<sfdisk(8)> command. It is
2359 not intended to be parsed.");
2361 ("sfdisk_kernel_geometry", (RString "partitions", [String "device"]), 101, [],
2363 "display the kernel geometry",
2365 This displays the kernel's idea of the geometry of C<device>.
2367 The result is in human-readable format, and not designed to
2370 ("sfdisk_disk_geometry", (RString "partitions", [String "device"]), 102, [],
2372 "display the disk geometry from the partition table",
2374 This displays the disk geometry of C<device> read from the
2375 partition table. Especially in the case where the underlying
2376 block device has been resized, this can be different from the
2377 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2379 The result is in human-readable format, and not designed to
2382 ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2384 "activate or deactivate all volume groups",
2386 This command activates or (if C<activate> is false) deactivates
2387 all logical volumes in all volume groups.
2388 If activated, then they are made known to the
2389 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2390 then those devices disappear.
2392 This command is the same as running C<vgchange -a y|n>");
2394 ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2396 "activate or deactivate some volume groups",
2398 This command activates or (if C<activate> is false) deactivates
2399 all logical volumes in the listed volume groups C<volgroups>.
2400 If activated, then they are made known to the
2401 kernel, ie. they appear as C</dev/mapper> devices. If deactivated,
2402 then those devices disappear.
2404 This command is the same as running C<vgchange -a y|n volgroups...>
2406 Note that if C<volgroups> is an empty list then B<all> volume groups
2407 are activated or deactivated.");
2409 ("lvresize", (RErr, [String "device"; Int "mbytes"]), 105, [],
2410 [InitNone, Always, TestOutput (
2411 [["sfdiskM"; "/dev/sda"; ","];
2412 ["pvcreate"; "/dev/sda1"];
2413 ["vgcreate"; "VG"; "/dev/sda1"];
2414 ["lvcreate"; "LV"; "VG"; "10"];
2415 ["mkfs"; "ext2"; "/dev/VG/LV"];
2416 ["mount"; "/dev/VG/LV"; "/"];
2417 ["write_file"; "/new"; "test content"; "0"];
2419 ["lvresize"; "/dev/VG/LV"; "20"];
2420 ["e2fsck_f"; "/dev/VG/LV"];
2421 ["resize2fs"; "/dev/VG/LV"];
2422 ["mount"; "/dev/VG/LV"; "/"];
2423 ["cat"; "/new"]], "test content")],
2424 "resize an LVM logical volume",
2426 This resizes (expands or shrinks) an existing LVM logical
2427 volume to C<mbytes>. When reducing, data in the reduced part
2430 ("resize2fs", (RErr, [String "device"]), 106, [],
2431 [], (* lvresize tests this *)
2432 "resize an ext2/ext3 filesystem",
2434 This resizes an ext2 or ext3 filesystem to match the size of
2435 the underlying device.
2437 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2438 on the C<device> before calling this command. For unknown reasons
2439 C<resize2fs> sometimes gives an error about this and sometimes not.
2440 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2441 calling this function.");
2443 ("find", (RStringList "names", [String "directory"]), 107, [],
2444 [InitBasicFS, Always, TestOutputList (
2445 [["find"; "/"]], ["lost+found"]);
2446 InitBasicFS, Always, TestOutputList (
2450 ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2451 InitBasicFS, Always, TestOutputList (
2452 [["mkdir_p"; "/a/b/c"];
2453 ["touch"; "/a/b/c/d"];
2454 ["find"; "/a/b/"]], ["c"; "c/d"])],
2455 "find all files and directories",
2457 This command lists out all files and directories, recursively,
2458 starting at C<directory>. It is essentially equivalent to
2459 running the shell command C<find directory -print> but some
2460 post-processing happens on the output, described below.
2462 This returns a list of strings I<without any prefix>. Thus
2463 if the directory structure was:
2469 then the returned list from C<guestfs_find> C</tmp> would be
2477 If C<directory> is not a directory, then this command returns
2480 The returned list is sorted.");
2482 ("e2fsck_f", (RErr, [String "device"]), 108, [],
2483 [], (* lvresize tests this *)
2484 "check an ext2/ext3 filesystem",
2486 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2487 filesystem checker on C<device>, noninteractively (C<-p>),
2488 even if the filesystem appears to be clean (C<-f>).
2490 This command is only needed because of C<guestfs_resize2fs>
2491 (q.v.). Normally you should use C<guestfs_fsck>.");
2493 ("sleep", (RErr, [Int "secs"]), 109, [],
2494 [InitNone, Always, TestRun (
2496 "sleep for some seconds",
2498 Sleep for C<secs> seconds.");
2500 ("ntfs_3g_probe", (RInt "status", [Bool "rw"; String "device"]), 110, [],
2501 [InitNone, Always, TestOutputInt (
2502 [["sfdiskM"; "/dev/sda"; ","];
2503 ["mkfs"; "ntfs"; "/dev/sda1"];
2504 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2505 InitNone, Always, TestOutputInt (
2506 [["sfdiskM"; "/dev/sda"; ","];
2507 ["mkfs"; "ext2"; "/dev/sda1"];
2508 ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2509 "probe NTFS volume",
2511 This command runs the L<ntfs-3g.probe(8)> command which probes
2512 an NTFS C<device> for mountability. (Not all NTFS volumes can
2513 be mounted read-write, and some cannot be mounted at all).
2515 C<rw> is a boolean flag. Set it to true if you want to test
2516 if the volume can be mounted read-write. Set it to false if
2517 you want to test if the volume can be mounted read-only.
2519 The return value is an integer which C<0> if the operation
2520 would succeed, or some non-zero value documented in the
2521 L<ntfs-3g.probe(8)> manual page.");
2523 ("sh", (RString "output", [String "command"]), 111, [],
2524 [], (* XXX needs tests *)
2525 "run a command via the shell",
2527 This call runs a command from the guest filesystem via the
2530 This is like C<guestfs_command>, but passes the command to:
2532 /bin/sh -c \"command\"
2534 Depending on the guest's shell, this usually results in
2535 wildcards being expanded, shell expressions being interpolated
2538 All the provisos about C<guestfs_command> apply to this call.");
2540 ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2541 [], (* XXX needs tests *)
2542 "run a command via the shell returning lines",
2544 This is the same as C<guestfs_sh>, but splits the result
2545 into a list of lines.
2547 See also: C<guestfs_command_lines>");
2549 ("glob_expand", (RStringList "paths", [String "pattern"]), 113, [],
2550 [InitBasicFS, Always, TestOutputList (
2551 [["mkdir_p"; "/a/b/c"];
2552 ["touch"; "/a/b/c/d"];
2553 ["touch"; "/a/b/c/e"];
2554 ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2555 InitBasicFS, Always, TestOutputList (
2556 [["mkdir_p"; "/a/b/c"];
2557 ["touch"; "/a/b/c/d"];
2558 ["touch"; "/a/b/c/e"];
2559 ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2560 InitBasicFS, Always, TestOutputList (
2561 [["mkdir_p"; "/a/b/c"];
2562 ["touch"; "/a/b/c/d"];
2563 ["touch"; "/a/b/c/e"];
2564 ["glob_expand"; "/a/*/x/*"]], [])],
2565 "expand a wildcard path",
2567 This command searches for all the pathnames matching
2568 C<pattern> according to the wildcard expansion rules
2571 If no paths match, then this returns an empty list
2572 (note: not an error).
2574 It is just a wrapper around the C L<glob(3)> function
2575 with flags C<GLOB_MARK|GLOB_BRACE>.
2576 See that manual page for more details.");
2578 ("scrub_device", (RErr, [String "device"]), 114, [DangerWillRobinson],
2579 [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2580 [["scrub_device"; "/dev/sdc"]])],
2581 "scrub (securely wipe) a device",
2583 This command writes patterns over C<device> to make data retrieval
2586 It is an interface to the L<scrub(1)> program. See that
2587 manual page for more details.");
2589 ("scrub_file", (RErr, [String "file"]), 115, [],
2590 [InitBasicFS, Always, TestRun (
2591 [["write_file"; "/file"; "content"; "0"];
2592 ["scrub_file"; "/file"]])],
2593 "scrub (securely wipe) a file",
2595 This command writes patterns over a file to make data retrieval
2598 The file is I<removed> after scrubbing.
2600 It is an interface to the L<scrub(1)> program. See that
2601 manual page for more details.");
2603 ("scrub_freespace", (RErr, [String "dir"]), 116, [],
2604 [], (* XXX needs testing *)
2605 "scrub (securely wipe) free space",
2607 This command creates the directory C<dir> and then fills it
2608 with files until the filesystem is full, and scrubs the files
2609 as for C<guestfs_scrub_file>, and deletes them.
2610 The intention is to scrub any free space on the partition
2613 It is an interface to the L<scrub(1)> program. See that
2614 manual page for more details.");
2616 ("mkdtemp", (RString "dir", [String "template"]), 117, [],
2617 [InitBasicFS, Always, TestRun (
2619 ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2620 "create a temporary directory",
2622 This command creates a temporary directory. The
2623 C<template> parameter should be a full pathname for the
2624 temporary directory name with the final six characters being
2627 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2628 the second one being suitable for Windows filesystems.
2630 The name of the temporary directory that was created
2633 The temporary directory is created with mode 0700
2634 and is owned by root.
2636 The caller is responsible for deleting the temporary
2637 directory and its contents after use.
2639 See also: L<mkdtemp(3)>");
2641 ("wc_l", (RInt "lines", [String "path"]), 118, [],
2642 [InitSquashFS, Always, TestOutputInt (
2643 [["wc_l"; "/10klines"]], 10000)],
2644 "count lines in a file",
2646 This command counts the lines in a file, using the
2647 C<wc -l> external command.");
2649 ("wc_w", (RInt "words", [String "path"]), 119, [],
2650 [InitSquashFS, Always, TestOutputInt (
2651 [["wc_w"; "/10klines"]], 10000)],
2652 "count words in a file",
2654 This command counts the words in a file, using the
2655 C<wc -w> external command.");
2657 ("wc_c", (RInt "chars", [String "path"]), 120, [],
2658 [InitSquashFS, Always, TestOutputInt (
2659 [["wc_c"; "/100kallspaces"]], 102400)],
2660 "count characters in a file",
2662 This command counts the characters in a file, using the
2663 C<wc -c> external command.");
2665 ("head", (RStringList "lines", [String "path"]), 121, [ProtocolLimitWarning],
2666 [InitSquashFS, Always, TestOutputList (
2667 [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2668 "return first 10 lines of a file",
2670 This command returns up to the first 10 lines of a file as
2671 a list of strings.");
2673 ("head_n", (RStringList "lines", [Int "nrlines"; String "path"]), 122, [ProtocolLimitWarning],
2674 [InitSquashFS, Always, TestOutputList (
2675 [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2676 InitSquashFS, Always, TestOutputList (
2677 [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2678 InitSquashFS, Always, TestOutputList (
2679 [["head_n"; "0"; "/10klines"]], [])],
2680 "return first N lines of a file",
2682 If the parameter C<nrlines> is a positive number, this returns the first
2683 C<nrlines> lines of the file C<path>.
2685 If the parameter C<nrlines> is a negative number, this returns lines
2686 from the file C<path>, excluding the last C<nrlines> lines.
2688 If the parameter C<nrlines> is zero, this returns an empty list.");
2690 ("tail", (RStringList "lines", [String "path"]), 123, [ProtocolLimitWarning],
2691 [InitSquashFS, Always, TestOutputList (
2692 [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2693 "return last 10 lines of a file",
2695 This command returns up to the last 10 lines of a file as
2696 a list of strings.");
2698 ("tail_n", (RStringList "lines", [Int "nrlines"; String "path"]), 124, [ProtocolLimitWarning],
2699 [InitSquashFS, Always, TestOutputList (
2700 [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2701 InitSquashFS, Always, TestOutputList (
2702 [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2703 InitSquashFS, Always, TestOutputList (
2704 [["tail_n"; "0"; "/10klines"]], [])],
2705 "return last N lines of a file",
2707 If the parameter C<nrlines> is a positive number, this returns the last
2708 C<nrlines> lines of the file C<path>.
2710 If the parameter C<nrlines> is a negative number, this returns lines
2711 from the file C<path>, starting with the C<-nrlines>th line.
2713 If the parameter C<nrlines> is zero, this returns an empty list.");
2715 ("df", (RString "output", []), 125, [],
2716 [], (* XXX Tricky to test because it depends on the exact format
2717 * of the 'df' command and other imponderables.
2719 "report file system disk space usage",
2721 This command runs the C<df> command to report disk space used.
2723 This command is mostly useful for interactive sessions. It
2724 is I<not> intended that you try to parse the output string.
2725 Use C<statvfs> from programs.");
2727 ("df_h", (RString "output", []), 126, [],
2728 [], (* XXX Tricky to test because it depends on the exact format
2729 * of the 'df' command and other imponderables.
2731 "report file system disk space usage (human readable)",
2733 This command runs the C<df -h> command to report disk space used
2734 in human-readable format.
2736 This command is mostly useful for interactive sessions. It
2737 is I<not> intended that you try to parse the output string.
2738 Use C<statvfs> from programs.");
2740 ("du", (RInt64 "sizekb", [String "path"]), 127, [],
2741 [InitSquashFS, Always, TestOutputInt (
2742 [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))],
2743 "estimate file space usage",
2745 This command runs the C<du -s> command to estimate file space
2748 C<path> can be a file or a directory. If C<path> is a directory
2749 then the estimate includes the contents of the directory and all
2750 subdirectories (recursively).
2752 The result is the estimated size in I<kilobytes>
2753 (ie. units of 1024 bytes).");
2755 ("initrd_list", (RStringList "filenames", [String "path"]), 128, [],
2756 [InitSquashFS, Always, TestOutputList (
2757 [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2758 "list files in an initrd",
2760 This command lists out files contained in an initrd.
2762 The files are listed without any initial C</> character. The
2763 files are listed in the order they appear (not necessarily
2764 alphabetical). Directory names are listed as separate items.
2766 Old Linux kernels (2.4 and earlier) used a compressed ext2
2767 filesystem as initrd. We I<only> support the newer initramfs
2768 format (compressed cpio files).");
2770 ("mount_loop", (RErr, [String "file"; String "mountpoint"]), 129, [],
2772 "mount a file using the loop device",
2774 This command lets you mount C<file> (a filesystem image
2775 in a file) on a mount point. It is entirely equivalent to
2776 the command C<mount -o loop file mountpoint>.");
2778 ("mkswap", (RErr, [String "device"]), 130, [],
2779 [InitEmpty, Always, TestRun (
2780 [["sfdiskM"; "/dev/sda"; ","];
2781 ["mkswap"; "/dev/sda1"]])],
2782 "create a swap partition",
2784 Create a swap partition on C<device>.");
2786 ("mkswap_L", (RErr, [String "label"; String "device"]), 131, [],
2787 [InitEmpty, Always, TestRun (
2788 [["sfdiskM"; "/dev/sda"; ","];
2789 ["mkswap_L"; "hello"; "/dev/sda1"]])],
2790 "create a swap partition with a label",
2792 Create a swap partition on C<device> with label C<label>.
2794 Note that you cannot attach a swap label to a block device
2795 (eg. C</dev/sda>), just to a partition. This appears to be
2796 a limitation of the kernel or swap tools.");
2798 ("mkswap_U", (RErr, [String "uuid"; String "device"]), 132, [],
2799 [InitEmpty, Always, TestRun (
2800 [["sfdiskM"; "/dev/sda"; ","];
2801 ["mkswap_U"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"; "/dev/sda1"]])],
2802 "create a swap partition with an explicit UUID",
2804 Create a swap partition on C<device> with UUID C<uuid>.");
2806 ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 133, [],
2807 [InitBasicFS, Always, TestOutputStruct (
2808 [["mknod"; "0o10777"; "0"; "0"; "/node"];
2809 (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2810 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2811 InitBasicFS, Always, TestOutputStruct (
2812 [["mknod"; "0o60777"; "66"; "99"; "/node"];
2813 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2814 "make block, character or FIFO devices",
2816 This call creates block or character special devices, or
2817 named pipes (FIFOs).
2819 The C<mode> parameter should be the mode, using the standard
2820 constants. C<devmajor> and C<devminor> are the
2821 device major and minor numbers, only used when creating block
2822 and character special devices.");
2824 ("mkfifo", (RErr, [Int "mode"; String "path"]), 134, [],
2825 [InitBasicFS, Always, TestOutputStruct (
2826 [["mkfifo"; "0o777"; "/node"];
2827 ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2828 "make FIFO (named pipe)",
2830 This call creates a FIFO (named pipe) called C<path> with
2831 mode C<mode>. It is just a convenient wrapper around
2832 C<guestfs_mknod>.");
2834 ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 135, [],
2835 [InitBasicFS, Always, TestOutputStruct (
2836 [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2837 ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2838 "make block device node",
2840 This call creates a block device node called C<path> with
2841 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2842 It is just a convenient wrapper around C<guestfs_mknod>.");
2844 ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; String "path"]), 136, [],
2845 [InitBasicFS, Always, TestOutputStruct (
2846 [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2847 ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2848 "make char device node",
2850 This call creates a char device node called C<path> with
2851 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2852 It is just a convenient wrapper around C<guestfs_mknod>.");
2854 ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2855 [], (* XXX umask is one of those stateful things that we should
2856 * reset between each test.
2858 "set file mode creation mask (umask)",
2860 This function sets the mask used for creating new files and
2861 device nodes to C<mask & 0777>.
2863 Typical umask values would be C<022> which creates new files
2864 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2865 C<002> which creates new files with permissions like
2866 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2868 The default umask is C<022>. This is important because it
2869 means that directories and device nodes will be created with
2870 C<0644> or C<0755> mode even if you specify C<0777>.
2872 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2874 This call returns the previous umask.");
2876 ("readdir", (RStructList ("entries", "dirent"), [String "dir"]), 138, [],
2878 "read directories entries",
2880 This returns the list of directory entries in directory C<dir>.
2882 All entries in the directory are returned, including C<.> and
2883 C<..>. The entries are I<not> sorted, but returned in the same
2884 order as the underlying filesystem.
2886 Also this call returns basic file type information about each
2887 file. The C<ftyp> field will contain one of the following characters:
2925 The L<readdir(3)> returned a C<d_type> field with an
2930 This function is primarily intended for use by programs. To
2931 get a simple list of names, use C<guestfs_ls>. To get a printable
2932 directory for human consumption, use C<guestfs_ll>.");
2934 ("sfdiskM", (RErr, [String "device"; StringList "lines"]), 139, [DangerWillRobinson],
2936 "create partitions on a block device",
2938 This is a simplified interface to the C<guestfs_sfdisk>
2939 command, where partition sizes are specified in megabytes
2940 only (rounded to the nearest cylinder) and you don't need
2941 to specify the cyls, heads and sectors parameters which
2942 were rarely if ever used anyway.
2944 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2946 ("zfile", (RString "description", [String "method"; String "path"]), 140, [DeprecatedBy "file"],
2948 "determine file type inside a compressed file",
2950 This command runs C<file> after first decompressing C<path>
2953 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2955 Since 1.0.63, use C<guestfs_file> instead which can now
2956 process compressed files.");
2958 ("getxattrs", (RStructList ("xattrs", "xattr"), [String "path"]), 141, [],
2960 "list extended attributes of a file or directory",
2962 This call lists the extended attributes of the file or directory
2965 At the system call level, this is a combination of the
2966 L<listxattr(2)> and L<getxattr(2)> calls.
2968 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2970 ("lgetxattrs", (RStructList ("xattrs", "xattr"), [String "path"]), 142, [],
2972 "list extended attributes of a file or directory",
2974 This is the same as C<guestfs_getxattrs>, but if C<path>
2975 is a symbolic link, then it returns the extended attributes
2976 of the link itself.");
2978 ("setxattr", (RErr, [String "xattr";
2979 String "val"; Int "vallen"; (* will be BufferIn *)
2980 String "path"]), 143, [],
2982 "set extended attribute of a file or directory",
2984 This call sets the extended attribute named C<xattr>
2985 of the file C<path> to the value C<val> (of length C<vallen>).
2986 The value is arbitrary 8 bit data.
2988 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
2990 ("lsetxattr", (RErr, [String "xattr";
2991 String "val"; Int "vallen"; (* will be BufferIn *)
2992 String "path"]), 144, [],
2994 "set extended attribute of a file or directory",
2996 This is the same as C<guestfs_setxattr>, but if C<path>
2997 is a symbolic link, then it sets an extended attribute
2998 of the link itself.");
3000 ("removexattr", (RErr, [String "xattr"; String "path"]), 145, [],
3002 "remove extended attribute of a file or directory",
3004 This call removes the extended attribute named C<xattr>
3005 of the file C<path>.
3007 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3009 ("lremovexattr", (RErr, [String "xattr"; String "path"]), 146, [],
3011 "remove extended attribute of a file or directory",
3013 This is the same as C<guestfs_removexattr>, but if C<path>
3014 is a symbolic link, then it removes an extended attribute
3015 of the link itself.");
3017 ("mountpoints", (RHashtable "mps", []), 147, [],
3021 This call is similar to C<guestfs_mounts>. That call returns
3022 a list of devices. This one returns a hash table (map) of
3023 device name to directory where the device is mounted.");
3025 ("mkmountpoint", (RErr, [String "path"]), 148, [],
3027 "create a mountpoint",
3029 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3030 specialized calls that can be used to create extra mountpoints
3031 before mounting the first filesystem.
3033 These calls are I<only> necessary in some very limited circumstances,
3034 mainly the case where you want to mount a mix of unrelated and/or
3035 read-only filesystems together.
3037 For example, live CDs often contain a \"Russian doll\" nest of
3038 filesystems, an ISO outer layer, with a squashfs image inside, with
3039 an ext2/3 image inside that. You can unpack this as follows
3042 add-ro Fedora-11-i686-Live.iso
3045 mkmountpoint /squash
3048 mount-loop /cd/LiveOS/squashfs.img /squash
3049 mount-loop /squash/LiveOS/ext3fs.img /ext3
3051 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3053 ("rmmountpoint", (RErr, [String "path"]), 149, [],
3055 "remove a mountpoint",
3057 This calls removes a mountpoint that was previously created
3058 with C<guestfs_mkmountpoint>. See C<guestfs_mkmountpoint>
3059 for full details.");
3061 ("read_file", (RBufferOut "content", [String "path"]), 150, [ProtocolLimitWarning],
3062 [InitSquashFS, Always, TestOutputBuffer (
3063 [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3066 This calls returns the contents of the file C<path> as a
3069 Unlike C<guestfs_cat>, this function can correctly
3070 handle files that contain embedded ASCII NUL characters.
3071 However unlike C<guestfs_download>, this function is limited
3072 in the total size of file that can be handled.");
3074 ("grep", (RStringList "lines", [String "regex"; String "path"]), 151, [ProtocolLimitWarning],
3075 [InitSquashFS, Always, TestOutputList (
3076 [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3077 InitSquashFS, Always, TestOutputList (
3078 [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3079 "return lines matching a pattern",
3081 This calls the external C<grep> program and returns the
3084 ("egrep", (RStringList "lines", [String "regex"; String "path"]), 152, [ProtocolLimitWarning],
3085 [InitSquashFS, Always, TestOutputList (
3086 [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3087 "return lines matching a pattern",
3089 This calls the external C<egrep> program and returns the
3092 ("fgrep", (RStringList "lines", [String "pattern"; String "path"]), 153, [ProtocolLimitWarning],
3093 [InitSquashFS, Always, TestOutputList (
3094 [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3095 "return lines matching a pattern",
3097 This calls the external C<fgrep> program and returns the
3100 ("grepi", (RStringList "lines", [String "regex"; String "path"]), 154, [ProtocolLimitWarning],
3101 [InitSquashFS, Always, TestOutputList (
3102 [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3103 "return lines matching a pattern",
3105 This calls the external C<grep -i> program and returns the
3108 ("egrepi", (RStringList "lines", [String "regex"; String "path"]), 155, [ProtocolLimitWarning],
3109 [InitSquashFS, Always, TestOutputList (
3110 [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3111 "return lines matching a pattern",
3113 This calls the external C<egrep -i> program and returns the
3116 ("fgrepi", (RStringList "lines", [String "pattern"; String "path"]), 156, [ProtocolLimitWarning],
3117 [InitSquashFS, Always, TestOutputList (
3118 [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3119 "return lines matching a pattern",
3121 This calls the external C<fgrep -i> program and returns the
3124 ("zgrep", (RStringList "lines", [String "regex"; String "path"]), 157, [ProtocolLimitWarning],
3125 [InitSquashFS, Always, TestOutputList (
3126 [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3127 "return lines matching a pattern",
3129 This calls the external C<zgrep> program and returns the
3132 ("zegrep", (RStringList "lines", [String "regex"; String "path"]), 158, [ProtocolLimitWarning],
3133 [InitSquashFS, Always, TestOutputList (
3134 [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3135 "return lines matching a pattern",
3137 This calls the external C<zegrep> program and returns the
3140 ("zfgrep", (RStringList "lines", [String "pattern"; String "path"]), 159, [ProtocolLimitWarning],
3141 [InitSquashFS, Always, TestOutputList (
3142 [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3143 "return lines matching a pattern",
3145 This calls the external C<zfgrep> program and returns the
3148 ("zgrepi", (RStringList "lines", [String "regex"; String "path"]), 160, [ProtocolLimitWarning],
3149 [InitSquashFS, Always, TestOutputList (
3150 [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3151 "return lines matching a pattern",
3153 This calls the external C<zgrep -i> program and returns the
3156 ("zegrepi", (RStringList "lines", [String "regex"; String "path"]), 161, [ProtocolLimitWarning],
3157 [InitSquashFS, Always, TestOutputList (
3158 [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3159 "return lines matching a pattern",
3161 This calls the external C<zegrep -i> program and returns the
3164 ("zfgrepi", (RStringList "lines", [String "pattern"; String "path"]), 162, [ProtocolLimitWarning],
3165 [InitSquashFS, Always, TestOutputList (
3166 [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3167 "return lines matching a pattern",
3169 This calls the external C<zfgrep -i> program and returns the
3172 ("realpath", (RString "rpath", [String "path"]), 163, [],
3173 [InitSquashFS, Always, TestOutput (
3174 [["realpath"; "/../directory"]], "/directory")],
3175 "canonicalized absolute pathname",
3177 Return the canonicalized absolute pathname of C<path>. The
3178 returned path has no C<.>, C<..> or symbolic link path elements.");
3180 ("ln", (RErr, [String "target"; String "linkname"]), 164, [],
3181 [InitBasicFS, Always, TestOutputStruct (
3184 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3185 "create a hard link",
3187 This command creates a hard link using the C<ln> command.");
3189 ("ln_f", (RErr, [String "target"; String "linkname"]), 165, [],
3190 [InitBasicFS, Always, TestOutputStruct (
3193 ["ln_f"; "/a"; "/b"];
3194 ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3195 "create a hard link",
3197 This command creates a hard link using the C<ln -f> command.
3198 The C<-f> option removes the link (C<linkname>) if it exists already.");
3200 ("ln_s", (RErr, [String "target"; String "linkname"]), 166, [],
3201 [InitBasicFS, Always, TestOutputStruct (
3203 ["ln_s"; "a"; "/b"];
3204 ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3205 "create a symbolic link",
3207 This command creates a symbolic link using the C<ln -s> command.");
3209 ("ln_sf", (RErr, [String "target"; String "linkname"]), 167, [],
3210 [InitBasicFS, Always, TestOutput (
3211 [["mkdir_p"; "/a/b"];
3212 ["touch"; "/a/b/c"];
3213 ["ln_sf"; "../d"; "/a/b/c"];
3214 ["readlink"; "/a/b/c"]], "../d")],
3215 "create a symbolic link",
3217 This command creates a symbolic link using the C<ln -sf> command,
3218 The C<-f> option removes the link (C<linkname>) if it exists already.");
3220 ("readlink", (RString "link", [String "path"]), 168, [],
3221 [] (* XXX tested above *),
3222 "read the target of a symbolic link",
3224 This command reads the target of a symbolic link.");
3226 ("fallocate", (RErr, [String "path"; Int "len"]), 169, [],
3227 [InitBasicFS, Always, TestOutputStruct (
3228 [["fallocate"; "/a"; "1000000"];
3229 ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3230 "preallocate a file in the guest filesystem",
3232 This command preallocates a file (containing zero bytes) named
3233 C<path> of size C<len> bytes. If the file exists already, it
3236 Do not confuse this with the guestfish-specific
3237 C<alloc> command which allocates a file in the host and
3238 attaches it as a device.");
3240 ("swapon_device", (RErr, [String "device"]), 170, [],
3241 [InitPartition, Always, TestRun (
3242 [["mkswap"; "/dev/sda1"];
3243 ["swapon_device"; "/dev/sda1"];
3244 ["swapoff_device"; "/dev/sda1"]])],
3245 "enable swap on device",
3247 This command enables the libguestfs appliance to use the
3248 swap device or partition named C<device>. The increased
3249 memory is made available for all commands, for example
3250 those run using C<guestfs_command> or C<guestfs_sh>.
3252 Note that you should not swap to existing guest swap
3253 partitions unless you know what you are doing. They may
3254 contain hibernation information, or other information that
3255 the guest doesn't want you to trash. You also risk leaking
3256 information about the host to the guest this way. Instead,
3257 attach a new host device to the guest and swap on that.");
3259 ("swapoff_device", (RErr, [String "device"]), 171, [],
3260 [], (* XXX tested by swapon_device *)
3261 "disable swap on device",
3263 This command disables the libguestfs appliance swap
3264 device or partition named C<device>.
3265 See C<guestfs_swapon_device>.");
3267 ("swapon_file", (RErr, [String "file"]), 172, [],
3268 [InitBasicFS, Always, TestRun (
3269 [["fallocate"; "/swap"; "8388608"];
3270 ["mkswap_file"; "/swap"];
3271 ["swapon_file"; "/swap"];
3272 ["swapoff_file"; "/swap"]])],
3273 "enable swap on file",
3275 This command enables swap to a file.
3276 See C<guestfs_swapon_device> for other notes.");
3278 ("swapoff_file", (RErr, [String "file"]), 173, [],
3279 [], (* XXX tested by swapon_file *)
3280 "disable swap on file",
3282 This command disables the libguestfs appliance swap on file.");
3284 ("swapon_label", (RErr, [String "label"]), 174, [],
3285 [InitEmpty, Always, TestRun (
3286 [["sfdiskM"; "/dev/sdb"; ","];
3287 ["mkswap_L"; "swapit"; "/dev/sdb1"];
3288 ["swapon_label"; "swapit"];
3289 ["swapoff_label"; "swapit"];
3290 ["zero"; "/dev/sdb"];
3291 ["blockdev_rereadpt"; "/dev/sdb"]])],
3292 "enable swap on labeled swap partition",
3294 This command enables swap to a labeled swap partition.
3295 See C<guestfs_swapon_device> for other notes.");
3297 ("swapoff_label", (RErr, [String "label"]), 175, [],
3298 [], (* XXX tested by swapon_label *)
3299 "disable swap on labeled swap partition",
3301 This command disables the libguestfs appliance swap on
3302 labeled swap partition.");
3304 ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3305 [InitEmpty, Always, TestRun (
3306 [["mkswap_U"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"; "/dev/sdb"];
3307 ["swapon_uuid"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"];
3308 ["swapoff_uuid"; "a3a61220-882b-4f61-89f4-cf24dcc7297d"]])],
3309 "enable swap on swap partition by UUID",
3311 This command enables swap to a swap partition with the given UUID.
3312 See C<guestfs_swapon_device> for other notes.");
3314 ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3315 [], (* XXX tested by swapon_uuid *)
3316 "disable swap on swap partition by UUID",
3318 This command disables the libguestfs appliance swap partition
3319 with the given UUID.");
3321 ("mkswap_file", (RErr, [String "path"]), 178, [],
3322 [InitBasicFS, Always, TestRun (
3323 [["fallocate"; "/swap"; "8388608"];
3324 ["mkswap_file"; "/swap"]])],
3325 "create a swap file",
3329 This command just writes a swap file signature to an existing
3330 file. To create the file itself, use something like C<guestfs_fallocate>.");
3332 ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3333 [InitSquashFS, Always, TestRun (
3334 [["inotify_init"; "0"]])],
3335 "create an inotify handle",
3337 This command creates a new inotify handle.
3338 The inotify subsystem can be used to notify events which happen to
3339 objects in the guest filesystem.
3341 C<maxevents> is the maximum number of events which will be
3342 queued up between calls to C<guestfs_inotify_read> or
3343 C<guestfs_inotify_files>.
3344 If this is passed as C<0>, then the kernel (or previously set)
3345 default is used. For Linux 2.6.29 the default was 16384 events.
3346 Beyond this limit, the kernel throws away events, but records
3347 the fact that it threw them away by setting a flag
3348 C<IN_Q_OVERFLOW> in the returned structure list (see
3349 C<guestfs_inotify_read>).
3351 Before any events are generated, you have to add some
3352 watches to the internal watch list. See:
3353 C<guestfs_inotify_add_watch>,
3354 C<guestfs_inotify_rm_watch> and
3355 C<guestfs_inotify_watch_all>.
3357 Queued up events should be read periodically by calling
3358 C<guestfs_inotify_read>
3359 (or C<guestfs_inotify_files> which is just a helpful
3360 wrapper around C<guestfs_inotify_read>). If you don't
3361 read the events out often enough then you risk the internal
3364 The handle should be closed after use by calling
3365 C<guestfs_inotify_close>. This also removes any
3366 watches automatically.
3368 See also L<inotify(7)> for an overview of the inotify interface
3369 as exposed by the Linux kernel, which is roughly what we expose
3370 via libguestfs. Note that there is one global inotify handle
3371 per libguestfs instance.");
3373 ("inotify_add_watch", (RInt64 "wd", [String "path"; Int "mask"]), 180, [],
3374 [InitBasicFS, Always, TestOutputList (
3375 [["inotify_init"; "0"];
3376 ["inotify_add_watch"; "/"; "1073741823"];
3379 ["inotify_files"]], ["a"; "b"])],
3380 "add an inotify watch",
3382 Watch C<path> for the events listed in C<mask>.
3384 Note that if C<path> is a directory then events within that
3385 directory are watched, but this does I<not> happen recursively
3386 (in subdirectories).
3388 Note for non-C or non-Linux callers: the inotify events are
3389 defined by the Linux kernel ABI and are listed in
3390 C</usr/include/sys/inotify.h>.");
3392 ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3394 "remove an inotify watch",
3396 Remove a previously defined inotify watch.
3397 See C<guestfs_inotify_add_watch>.");
3399 ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3401 "return list of inotify events",
3403 Return the complete queue of events that have happened
3404 since the previous read call.
3406 If no events have happened, this returns an empty list.
3408 I<Note>: In order to make sure that all events have been
3409 read, you must call this function repeatedly until it
3410 returns an empty list. The reason is that the call will
3411 read events up to the maximum appliance-to-host message
3412 size and leave remaining events in the queue.");
3414 ("inotify_files", (RStringList "paths", []), 183, [],
3416 "return list of watched files that had events",
3418 This function is a helpful wrapper around C<guestfs_inotify_read>
3419 which just returns a list of pathnames of objects that were
3420 touched. The returned pathnames are sorted and deduplicated.");
3422 ("inotify_close", (RErr, []), 184, [],
3424 "close the inotify handle",
3426 This closes the inotify handle which was previously
3427 opened by inotify_init. It removes all watches, throws
3428 away any pending events, and deallocates all resources.");
3430 ("setcon", (RErr, [String "context"]), 185, [],
3432 "set SELinux security context",
3434 This sets the SELinux security context of the daemon
3435 to the string C<context>.
3437 See the documentation about SELINUX in L<guestfs(3)>.");
3439 ("getcon", (RString "context", []), 186, [],
3441 "get SELinux security context",
3443 This gets the SELinux security context of the daemon.
3445 See the documentation about SELINUX in L<guestfs(3)>,
3446 and C<guestfs_setcon>");
3450 let all_functions = non_daemon_functions @ daemon_functions
3452 (* In some places we want the functions to be displayed sorted
3453 * alphabetically, so this is useful:
3455 let all_functions_sorted =
3456 List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3457 compare n1 n2) all_functions
3459 (* Field types for structures. *)
3461 | FChar (* C 'char' (really, a 7 bit byte). *)
3462 | FString (* nul-terminated ASCII string, NOT NULL. *)
3463 | FBuffer (* opaque buffer of bytes, (char *, int) pair *)
3468 | FBytes (* Any int measure that counts bytes. *)
3469 | FUUID (* 32 bytes long, NOT nul-terminated. *)
3470 | FOptPercent (* [0..100], or -1 meaning "not present". *)
3472 (* Because we generate extra parsing code for LVM command line tools,
3473 * we have to pull out the LVM columns separately here.
3483 "pv_attr", FString (* XXX *);
3484 "pv_pe_count", FInt64;
3485 "pv_pe_alloc_count", FInt64;
3488 "pv_mda_count", FInt64;
3489 "pv_mda_free", FBytes;
3490 (* Not in Fedora 10:
3491 "pv_mda_size", FBytes;
3498 "vg_attr", FString (* XXX *);
3501 "vg_sysid", FString;
3502 "vg_extent_size", FBytes;
3503 "vg_extent_count", FInt64;
3504 "vg_free_count", FInt64;
3509 "snap_count", FInt64;
3512 "vg_mda_count", FInt64;
3513 "vg_mda_free", FBytes;
3514 (* Not in Fedora 10:
3515 "vg_mda_size", FBytes;
3521 "lv_attr", FString (* XXX *);
3524 "lv_kernel_major", FInt64;
3525 "lv_kernel_minor", FInt64;
3527 "seg_count", FInt64;
3529 "snap_percent", FOptPercent;
3530 "copy_percent", FOptPercent;
3533 "mirror_log", FString;
3537 (* Names and fields in all structures (in RStruct and RStructList)
3541 (* The old RIntBool return type, only ever used for aug_defnode. Do
3542 * not use this struct in any new code.
3545 "i", FInt32; (* for historical compatibility *)
3546 "b", FInt32; (* for historical compatibility *)
3549 (* LVM PVs, VGs, LVs. *)
3550 "lvm_pv", lvm_pv_cols;
3551 "lvm_vg", lvm_vg_cols;
3552 "lvm_lv", lvm_lv_cols;
3554 (* Column names and types from stat structures.
3555 * NB. Can't use things like 'st_atime' because glibc header files
3556 * define some of these as macros. Ugh.
3587 (* Column names in dirent structure. *)
3590 (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3595 (* Version numbers. *)
3603 (* Extended attribute. *)
3605 "attrname", FString;
3609 (* Inotify events. *)
3613 "in_cookie", FUInt32;
3616 ] (* end of structs *)
3618 (* Ugh, Java has to be different ..
3619 * These names are also used by the Haskell bindings.
3621 let java_structs = [
3622 "int_bool", "IntBool";
3627 "statvfs", "StatVFS";
3629 "version", "Version";
3631 "inotify_event", "INotifyEvent";
3634 (* Used for testing language bindings. *)
3636 | CallString of string
3637 | CallOptString of string option
3638 | CallStringList of string list
3642 (* Used to memoize the result of pod2text. *)
3643 let pod2text_memo_filename = "src/.pod2text.data"
3644 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3646 let chan = open_in pod2text_memo_filename in
3647 let v = input_value chan in
3651 _ -> Hashtbl.create 13
3653 (* Useful functions.
3654 * Note we don't want to use any external OCaml libraries which
3655 * makes this a bit harder than it should be.
3657 let failwithf fs = ksprintf failwith fs
3659 let replace_char s c1 c2 =
3660 let s2 = String.copy s in
3661 let r = ref false in
3662 for i = 0 to String.length s2 - 1 do
3663 if String.unsafe_get s2 i = c1 then (
3664 String.unsafe_set s2 i c2;
3668 if not !r then s else s2
3672 (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3674 let triml ?(test = isspace) str =
3676 let n = ref (String.length str) in
3677 while !n > 0 && test str.[!i]; do
3682 else String.sub str !i !n
3684 let trimr ?(test = isspace) str =
3685 let n = ref (String.length str) in
3686 while !n > 0 && test str.[!n-1]; do
3689 if !n = String.length str then str
3690 else String.sub str 0 !n
3692 let trim ?(test = isspace) str =
3693 trimr ~test (triml ~test str)
3695 let rec find s sub =
3696 let len = String.length s in
3697 let sublen = String.length sub in
3699 if i <= len-sublen then (
3701 if j < sublen then (
3702 if s.[i+j] = sub.[j] then loop2 (j+1)
3708 if r = -1 then loop (i+1) else r
3714 let rec replace_str s s1 s2 =
3715 let len = String.length s in
3716 let sublen = String.length s1 in
3717 let i = find s s1 in
3720 let s' = String.sub s 0 i in
3721 let s'' = String.sub s (i+sublen) (len-i-sublen) in
3722 s' ^ s2 ^ replace_str s'' s1 s2
3725 let rec string_split sep str =
3726 let len = String.length str in
3727 let seplen = String.length sep in
3728 let i = find str sep in
3729 if i = -1 then [str]
3731 let s' = String.sub str 0 i in
3732 let s'' = String.sub str (i+seplen) (len-i-seplen) in
3733 s' :: string_split sep s''
3736 let files_equal n1 n2 =
3737 let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3738 match Sys.command cmd with
3741 | i -> failwithf "%s: failed with error code %d" cmd i
3743 let rec filter_map f = function
3747 | Some y -> y :: filter_map f xs
3748 | None -> filter_map f xs
3750 let rec find_map f = function
3751 | [] -> raise Not_found
3755 | None -> find_map f xs
3758 let rec loop i = function
3760 | x :: xs -> f i x; loop (i+1) xs
3765 let rec loop i = function
3767 | x :: xs -> let r = f i x in r :: loop (i+1) xs
3771 let name_of_argt = function
3772 | String n | OptString n | StringList n | Bool n | Int n
3773 | FileIn n | FileOut n -> n
3775 let java_name_of_struct typ =
3776 try List.assoc typ java_structs
3779 "java_name_of_struct: no java_structs entry corresponding to %s" typ
3781 let cols_of_struct typ =
3782 try List.assoc typ structs
3784 failwithf "cols_of_struct: unknown struct %s" typ
3786 let seq_of_test = function
3787 | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3788 | TestOutputListOfDevices (s, _)
3789 | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3790 | TestOutputTrue s | TestOutputFalse s
3791 | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3792 | TestOutputStruct (s, _)
3793 | TestLastFail s -> s
3795 (* Handling for function flags. *)
3796 let protocol_limit_warning =
3797 "Because of the message protocol, there is a transfer limit
3798 of somewhere between 2MB and 4MB. To transfer large files you should use
3801 let danger_will_robinson =
3802 "B<This command is dangerous. Without careful use you
3803 can easily destroy all your data>."
3805 let deprecation_notice flags =
3808 find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
3810 sprintf "This function is deprecated.
3811 In new code, use the C<%s> call instead.
3813 Deprecated functions will not be removed from the API, but the
3814 fact that they are deprecated indicates that there are problems
3815 with correct use of these functions." alt in
3820 (* Check function names etc. for consistency. *)
3821 let check_functions () =
3822 let contains_uppercase str =
3823 let len = String.length str in
3825 if i >= len then false
3828 if c >= 'A' && c <= 'Z' then true
3835 (* Check function names. *)
3837 fun (name, _, _, _, _, _, _) ->
3838 if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
3839 failwithf "function name %s does not need 'guestfs' prefix" name;
3841 failwithf "function name is empty";
3842 if name.[0] < 'a' || name.[0] > 'z' then
3843 failwithf "function name %s must start with lowercase a-z" name;
3844 if String.contains name '-' then
3845 failwithf "function name %s should not contain '-', use '_' instead."
3849 (* Check function parameter/return names. *)
3851 fun (name, style, _, _, _, _, _) ->
3852 let check_arg_ret_name n =
3853 if contains_uppercase n then
3854 failwithf "%s param/ret %s should not contain uppercase chars"
3856 if String.contains n '-' || String.contains n '_' then
3857 failwithf "%s param/ret %s should not contain '-' or '_'"
3860 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;
3861 if n = "int" || n = "char" || n = "short" || n = "long" then
3862 failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
3863 if n = "i" || n = "n" then
3864 failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
3865 if n = "argv" || n = "args" then
3866 failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
3869 (match fst style with
3871 | RInt n | RInt64 n | RBool n
3872 | RConstString n | RConstOptString n | RString n
3873 | RStringList n | RStruct (n, _) | RStructList (n, _)
3874 | RHashtable n | RBufferOut n ->
3875 check_arg_ret_name n
3877 List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
3880 (* Check short descriptions. *)
3882 fun (name, _, _, _, _, shortdesc, _) ->
3883 if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
3884 failwithf "short description of %s should begin with lowercase." name;
3885 let c = shortdesc.[String.length shortdesc-1] in
3886 if c = '\n' || c = '.' then
3887 failwithf "short description of %s should not end with . or \\n." name
3890 (* Check long dscriptions. *)
3892 fun (name, _, _, _, _, _, longdesc) ->
3893 if longdesc.[String.length longdesc-1] = '\n' then
3894 failwithf "long description of %s should not end with \\n." name
3897 (* Check proc_nrs. *)
3899 fun (name, _, proc_nr, _, _, _, _) ->
3900 if proc_nr <= 0 then
3901 failwithf "daemon function %s should have proc_nr > 0" name
3905 fun (name, _, proc_nr, _, _, _, _) ->
3906 if proc_nr <> -1 then
3907 failwithf "non-daemon function %s should have proc_nr -1" name
3908 ) non_daemon_functions;
3911 List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
3914 List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
3915 let rec loop = function
3918 | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
3920 | (name1,nr1) :: (name2,nr2) :: _ ->
3921 failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
3929 (* Ignore functions that have no tests. We generate a
3930 * warning when the user does 'make check' instead.
3932 | name, _, _, _, [], _, _ -> ()
3933 | name, _, _, _, tests, _, _ ->
3937 match seq_of_test test with
3939 failwithf "%s has a test containing an empty sequence" name
3940 | cmds -> List.map List.hd cmds
3942 let funcs = List.flatten funcs in
3944 let tested = List.mem name funcs in
3947 failwithf "function %s has tests but does not test itself" name
3950 (* 'pr' prints to the current output file. *)
3951 let chan = ref stdout
3952 let pr fs = ksprintf (output_string !chan) fs
3954 (* Generate a header block in a number of standard styles. *)
3955 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
3956 type license = GPLv2 | LGPLv2
3958 let generate_header comment license =
3959 let c = match comment with
3960 | CStyle -> pr "/* "; " *"
3961 | HashStyle -> pr "# "; "#"
3962 | OCamlStyle -> pr "(* "; " *"
3963 | HaskellStyle -> pr "{- "; " " in
3964 pr "libguestfs generated file\n";
3965 pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
3966 pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
3968 pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
3972 pr "%s This program is free software; you can redistribute it and/or modify\n" c;
3973 pr "%s it under the terms of the GNU General Public License as published by\n" c;
3974 pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
3975 pr "%s (at your option) any later version.\n" c;
3977 pr "%s This program is distributed in the hope that it will be useful,\n" c;
3978 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
3979 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" c;
3980 pr "%s GNU General Public License for more details.\n" c;
3982 pr "%s You should have received a copy of the GNU General Public License along\n" c;
3983 pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
3984 pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
3987 pr "%s This library is free software; you can redistribute it and/or\n" c;
3988 pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
3989 pr "%s License as published by the Free Software Foundation; either\n" c;
3990 pr "%s version 2 of the License, or (at your option) any later version.\n" c;
3992 pr "%s This library is distributed in the hope that it will be useful,\n" c;
3993 pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
3994 pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" c;
3995 pr "%s Lesser General Public License for more details.\n" c;
3997 pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
3998 pr "%s License along with this library; if not, write to the Free Software\n" c;
3999 pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4002 | CStyle -> pr " */\n"
4004 | OCamlStyle -> pr " *)\n"
4005 | HaskellStyle -> pr "-}\n"
4009 (* Start of main code generation functions below this line. *)
4011 (* Generate the pod documentation for the C API. *)
4012 let rec generate_actions_pod () =
4014 fun (shortname, style, _, flags, _, _, longdesc) ->
4015 if not (List.mem NotInDocs flags) then (
4016 let name = "guestfs_" ^ shortname in
4017 pr "=head2 %s\n\n" name;
4019 generate_prototype ~extern:false ~handle:"handle" name style;
4021 pr "%s\n\n" longdesc;
4022 (match fst style with
4024 pr "This function returns 0 on success or -1 on error.\n\n"
4026 pr "On error this function returns -1.\n\n"
4028 pr "On error this function returns -1.\n\n"
4030 pr "This function returns a C truth value on success or -1 on error.\n\n"
4032 pr "This function returns a string, or NULL on error.
4033 The string is owned by the guest handle and must I<not> be freed.\n\n"
4034 | RConstOptString _ ->
4035 pr "This function returns a string which may be NULL.
4036 There is way to return an error from this function.
4037 The string is owned by the guest handle and must I<not> be freed.\n\n"
4039 pr "This function returns a string, or NULL on error.
4040 I<The caller must free the returned string after use>.\n\n"
4042 pr "This function returns a NULL-terminated array of strings
4043 (like L<environ(3)>), or NULL if there was an error.
4044 I<The caller must free the strings and the array after use>.\n\n"
4045 | RStruct (_, typ) ->
4046 pr "This function returns a C<struct guestfs_%s *>,
4047 or NULL if there was an error.
4048 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4049 | RStructList (_, typ) ->
4050 pr "This function returns a C<struct guestfs_%s_list *>
4051 (see E<lt>guestfs-structs.hE<gt>),
4052 or NULL if there was an error.
4053 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4055 pr "This function returns a NULL-terminated array of
4056 strings, or NULL if there was an error.
4057 The array of strings will always have length C<2n+1>, where
4058 C<n> keys and values alternate, followed by the trailing NULL entry.
4059 I<The caller must free the strings and the array after use>.\n\n"
4061 pr "This function returns a buffer, or NULL on error.
4062 The size of the returned buffer is written to C<*size_r>.
4063 I<The caller must free the returned buffer after use>.\n\n"
4065 if List.mem ProtocolLimitWarning flags then
4066 pr "%s\n\n" protocol_limit_warning;
4067 if List.mem DangerWillRobinson flags then
4068 pr "%s\n\n" danger_will_robinson;
4069 match deprecation_notice flags with
4071 | Some txt -> pr "%s\n\n" txt
4073 ) all_functions_sorted
4075 and generate_structs_pod () =
4076 (* Structs documentation. *)
4079 pr "=head2 guestfs_%s\n" typ;
4081 pr " struct guestfs_%s {\n" typ;
4084 | name, FChar -> pr " char %s;\n" name
4085 | name, FUInt32 -> pr " uint32_t %s;\n" name
4086 | name, FInt32 -> pr " int32_t %s;\n" name
4087 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4088 | name, FInt64 -> pr " int64_t %s;\n" name
4089 | name, FString -> pr " char *%s;\n" name
4091 pr " /* The next two fields describe a byte array. */\n";
4092 pr " uint32_t %s_len;\n" name;
4093 pr " char *%s;\n" name
4095 pr " /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4096 pr " char %s[32];\n" name
4097 | name, FOptPercent ->
4098 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
4099 pr " float %s;\n" name
4103 pr " struct guestfs_%s_list {\n" typ;
4104 pr " uint32_t len; /* Number of elements in list. */\n";
4105 pr " struct guestfs_%s *val; /* Elements. */\n" typ;
4108 pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4109 pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4114 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4115 * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4117 * We have to use an underscore instead of a dash because otherwise
4118 * rpcgen generates incorrect code.
4120 * This header is NOT exported to clients, but see also generate_structs_h.
4122 and generate_xdr () =
4123 generate_header CStyle LGPLv2;
4125 (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4126 pr "typedef string str<>;\n";
4129 (* Internal structures. *)
4133 pr "struct guestfs_int_%s {\n" typ;
4135 | name, FChar -> pr " char %s;\n" name
4136 | name, FString -> pr " string %s<>;\n" name
4137 | name, FBuffer -> pr " opaque %s<>;\n" name
4138 | name, FUUID -> pr " opaque %s[32];\n" name
4139 | name, (FInt32|FUInt32) -> pr " int %s;\n" name
4140 | name, (FInt64|FUInt64|FBytes) -> pr " hyper %s;\n" name
4141 | name, FOptPercent -> pr " float %s;\n" name
4145 pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4150 fun (shortname, style, _, _, _, _, _) ->
4151 let name = "guestfs_" ^ shortname in
4153 (match snd style with
4156 pr "struct %s_args {\n" name;
4159 | String n -> pr " string %s<>;\n" n
4160 | OptString n -> pr " str *%s;\n" n
4161 | StringList n -> pr " str %s<>;\n" n
4162 | Bool n -> pr " bool %s;\n" n
4163 | Int n -> pr " int %s;\n" n
4164 | FileIn _ | FileOut _ -> ()
4168 (match fst style with
4171 pr "struct %s_ret {\n" name;
4175 pr "struct %s_ret {\n" name;
4176 pr " hyper %s;\n" n;
4179 pr "struct %s_ret {\n" name;
4182 | RConstString _ | RConstOptString _ ->
4183 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4185 pr "struct %s_ret {\n" name;
4186 pr " string %s<>;\n" n;
4189 pr "struct %s_ret {\n" name;
4190 pr " str %s<>;\n" n;
4192 | RStruct (n, typ) ->
4193 pr "struct %s_ret {\n" name;
4194 pr " guestfs_int_%s %s;\n" typ n;
4196 | RStructList (n, typ) ->
4197 pr "struct %s_ret {\n" name;
4198 pr " guestfs_int_%s_list %s;\n" typ n;
4201 pr "struct %s_ret {\n" name;
4202 pr " str %s<>;\n" n;
4205 pr "struct %s_ret {\n" name;
4206 pr " opaque %s<>;\n" n;
4211 (* Table of procedure numbers. *)
4212 pr "enum guestfs_procedure {\n";
4214 fun (shortname, _, proc_nr, _, _, _, _) ->
4215 pr " GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4217 pr " GUESTFS_PROC_NR_PROCS\n";
4221 (* Having to choose a maximum message size is annoying for several
4222 * reasons (it limits what we can do in the API), but it (a) makes
4223 * the protocol a lot simpler, and (b) provides a bound on the size
4224 * of the daemon which operates in limited memory space. For large
4225 * file transfers you should use FTP.
4227 pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4230 (* Message header, etc. *)
4232 /* The communication protocol is now documented in the guestfs(3)
4236 const GUESTFS_PROGRAM = 0x2000F5F5;
4237 const GUESTFS_PROTOCOL_VERSION = 1;
4239 /* These constants must be larger than any possible message length. */
4240 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4241 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4243 enum guestfs_message_direction {
4244 GUESTFS_DIRECTION_CALL = 0, /* client -> daemon */
4245 GUESTFS_DIRECTION_REPLY = 1 /* daemon -> client */
4248 enum guestfs_message_status {
4249 GUESTFS_STATUS_OK = 0,
4250 GUESTFS_STATUS_ERROR = 1
4253 const GUESTFS_ERROR_LEN = 256;
4255 struct guestfs_message_error {
4256 string error_message<GUESTFS_ERROR_LEN>;
4259 struct guestfs_message_header {
4260 unsigned prog; /* GUESTFS_PROGRAM */
4261 unsigned vers; /* GUESTFS_PROTOCOL_VERSION */
4262 guestfs_procedure proc; /* GUESTFS_PROC_x */
4263 guestfs_message_direction direction;
4264 unsigned serial; /* message serial number */
4265 guestfs_message_status status;
4268 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4270 struct guestfs_chunk {
4271 int cancel; /* if non-zero, transfer is cancelled */
4272 /* data size is 0 bytes if the transfer has finished successfully */
4273 opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4277 (* Generate the guestfs-structs.h file. *)
4278 and generate_structs_h () =
4279 generate_header CStyle LGPLv2;
4281 (* This is a public exported header file containing various
4282 * structures. The structures are carefully written to have
4283 * exactly the same in-memory format as the XDR structures that
4284 * we use on the wire to the daemon. The reason for creating
4285 * copies of these structures here is just so we don't have to
4286 * export the whole of guestfs_protocol.h (which includes much
4287 * unrelated and XDR-dependent stuff that we don't want to be
4288 * public, or required by clients).
4290 * To reiterate, we will pass these structures to and from the
4291 * client with a simple assignment or memcpy, so the format
4292 * must be identical to what rpcgen / the RFC defines.
4295 (* Public structures. *)
4298 pr "struct guestfs_%s {\n" typ;
4301 | name, FChar -> pr " char %s;\n" name
4302 | name, FString -> pr " char *%s;\n" name
4304 pr " uint32_t %s_len;\n" name;
4305 pr " char *%s;\n" name
4306 | name, FUUID -> pr " char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4307 | name, FUInt32 -> pr " uint32_t %s;\n" name
4308 | name, FInt32 -> pr " int32_t %s;\n" name
4309 | name, (FUInt64|FBytes) -> pr " uint64_t %s;\n" name
4310 | name, FInt64 -> pr " int64_t %s;\n" name
4311 | name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
4315 pr "struct guestfs_%s_list {\n" typ;
4316 pr " uint32_t len;\n";
4317 pr " struct guestfs_%s *val;\n" typ;
4320 pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4321 pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4325 (* Generate the guestfs-actions.h file. *)
4326 and generate_actions_h () =
4327 generate_header CStyle LGPLv2;
4329 fun (shortname, style, _, _, _, _, _) ->
4330 let name = "guestfs_" ^ shortname in
4331 generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4335 (* Generate the client-side dispatch stubs. *)
4336 and generate_client_actions () =
4337 generate_header CStyle LGPLv2;
4343 #include \"guestfs.h\"
4344 #include \"guestfs_protocol.h\"
4346 #define error guestfs_error
4347 #define perrorf guestfs_perrorf
4348 #define safe_malloc guestfs_safe_malloc
4349 #define safe_realloc guestfs_safe_realloc
4350 #define safe_strdup guestfs_safe_strdup
4351 #define safe_memdup guestfs_safe_memdup
4353 /* Check the return message from a call for validity. */
4355 check_reply_header (guestfs_h *g,
4356 const struct guestfs_message_header *hdr,
4357 int proc_nr, int serial)
4359 if (hdr->prog != GUESTFS_PROGRAM) {
4360 error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4363 if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4364 error (g, \"wrong protocol version (%%d/%%d)\",
4365 hdr->vers, GUESTFS_PROTOCOL_VERSION);
4368 if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4369 error (g, \"unexpected message direction (%%d/%%d)\",
4370 hdr->direction, GUESTFS_DIRECTION_REPLY);
4373 if (hdr->proc != proc_nr) {
4374 error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4377 if (hdr->serial != serial) {
4378 error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4385 /* Check we are in the right state to run a high-level action. */
4387 check_state (guestfs_h *g, const char *caller)
4389 if (!guestfs_is_ready (g)) {
4390 if (guestfs_is_config (g))
4391 error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4393 else if (guestfs_is_launching (g))
4394 error (g, \"%%s: call wait_ready() before using this function\",
4397 error (g, \"%%s called from the wrong state, %%d != READY\",
4398 caller, guestfs_get_state (g));
4406 (* Client-side stubs for each function. *)
4408 fun (shortname, style, _, _, _, _, _) ->
4409 let name = "guestfs_" ^ shortname in
4411 (* Generate the context struct which stores the high-level
4412 * state between callback functions.
4414 pr "struct %s_ctx {\n" shortname;
4415 pr " /* This flag is set by the callbacks, so we know we've done\n";
4416 pr " * the callbacks as expected, and in the right sequence.\n";
4417 pr " * 0 = not called, 1 = reply_cb called.\n";
4419 pr " int cb_sequence;\n";
4420 pr " struct guestfs_message_header hdr;\n";
4421 pr " struct guestfs_message_error err;\n";
4422 (match fst style with
4424 | RConstString _ | RConstOptString _ ->
4425 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4427 | RBool _ | RString _ | RStringList _
4428 | RStruct _ | RStructList _
4429 | RHashtable _ | RBufferOut _ ->
4430 pr " struct %s_ret ret;\n" name
4435 (* Generate the reply callback function. *)
4436 pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4438 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4439 pr " struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4441 pr " /* This should definitely not happen. */\n";
4442 pr " if (ctx->cb_sequence != 0) {\n";
4443 pr " ctx->cb_sequence = 9999;\n";
4444 pr " error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4448 pr " ml->main_loop_quit (ml, g);\n";
4450 pr " if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4451 pr " error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4454 pr " if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4455 pr " if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4456 pr " error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4463 (match fst style with
4465 | RConstString _ | RConstOptString _ ->
4466 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4468 | RBool _ | RString _ | RStringList _
4469 | RStruct _ | RStructList _
4470 | RHashtable _ | RBufferOut _ ->
4471 pr " if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4472 pr " error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4478 pr " ctx->cb_sequence = 1;\n";
4481 (* Generate the action stub. *)
4482 generate_prototype ~extern:false ~semicolon:false ~newline:true
4483 ~handle:"g" name style;
4486 match fst style with
4487 | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4488 | RConstString _ | RConstOptString _ ->
4489 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4490 | RString _ | RStringList _
4491 | RStruct _ | RStructList _
4492 | RHashtable _ | RBufferOut _ ->
4497 (match snd style with
4499 | _ -> pr " struct %s_args args;\n" name
4502 pr " struct %s_ctx ctx;\n" shortname;
4503 pr " guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4504 pr " int serial;\n";
4506 pr " if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4507 pr " guestfs_set_busy (g);\n";
4509 pr " memset (&ctx, 0, sizeof ctx);\n";
4512 (* Send the main header and arguments. *)
4513 (match snd style with
4515 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4516 (String.uppercase shortname)
4521 pr " args.%s = (char *) %s;\n" n n
4523 pr " args.%s = %s ? (char **) &%s : NULL;\n" n n n
4525 pr " args.%s.%s_val = (char **) %s;\n" n n n;
4526 pr " for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4528 pr " args.%s = %s;\n" n n
4530 pr " args.%s = %s;\n" n n
4531 | FileIn _ | FileOut _ -> ()
4533 pr " serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4534 (String.uppercase shortname);
4535 pr " (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4538 pr " if (serial == -1) {\n";
4539 pr " guestfs_end_busy (g);\n";
4540 pr " return %s;\n" error_code;
4544 (* Send any additional files (FileIn) requested. *)
4545 let need_read_reply_label = ref false in
4552 pr " r = guestfs__send_file_sync (g, %s);\n" n;
4553 pr " if (r == -1) {\n";
4554 pr " guestfs_end_busy (g);\n";
4555 pr " return %s;\n" error_code;
4557 pr " if (r == -2) /* daemon cancelled */\n";
4558 pr " goto read_reply;\n";
4559 need_read_reply_label := true;
4565 (* Wait for the reply from the remote end. *)
4566 if !need_read_reply_label then pr " read_reply:\n";
4567 pr " guestfs__switch_to_receiving (g);\n";
4568 pr " ctx.cb_sequence = 0;\n";
4569 pr " guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4570 pr " (void) ml->main_loop_run (ml, g);\n";
4571 pr " guestfs_set_reply_callback (g, NULL, NULL);\n";
4572 pr " if (ctx.cb_sequence != 1) {\n";
4573 pr " error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4574 pr " guestfs_end_busy (g);\n";
4575 pr " return %s;\n" error_code;
4579 pr " if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4580 (String.uppercase shortname);
4581 pr " guestfs_end_busy (g);\n";
4582 pr " return %s;\n" error_code;
4586 pr " if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4587 pr " error (g, \"%%s\", ctx.err.error_message);\n";
4588 pr " free (ctx.err.error_message);\n";
4589 pr " guestfs_end_busy (g);\n";
4590 pr " return %s;\n" error_code;
4594 (* Expecting to receive further files (FileOut)? *)
4598 pr " if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4599 pr " guestfs_end_busy (g);\n";
4600 pr " return %s;\n" error_code;
4606 pr " guestfs_end_busy (g);\n";
4608 (match fst style with
4609 | RErr -> pr " return 0;\n"
4610 | RInt n | RInt64 n | RBool n ->
4611 pr " return ctx.ret.%s;\n" n
4612 | RConstString _ | RConstOptString _ ->
4613 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4615 pr " return ctx.ret.%s; /* caller will free */\n" n
4616 | RStringList n | RHashtable n ->
4617 pr " /* caller will free this, but we need to add a NULL entry */\n";
4618 pr " ctx.ret.%s.%s_val =\n" n n;
4619 pr " safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4620 pr " sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4622 pr " ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4623 pr " return ctx.ret.%s.%s_val;\n" n n
4625 pr " /* caller will free this */\n";
4626 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4627 | RStructList (n, _) ->
4628 pr " /* caller will free this */\n";
4629 pr " return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4631 pr " *size_r = ctx.ret.%s.%s_len;\n" n n;
4632 pr " return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4638 (* Functions to free structures. *)
4639 pr "/* Structure-freeing functions. These rely on the fact that the\n";
4640 pr " * structure format is identical to the XDR format. See note in\n";
4641 pr " * generator.ml.\n";
4648 pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4650 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4656 pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4658 pr " xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4665 (* Generate daemon/actions.h. *)
4666 and generate_daemon_actions_h () =
4667 generate_header CStyle GPLv2;
4669 pr "#include \"../src/guestfs_protocol.h\"\n";
4673 fun (name, style, _, _, _, _, _) ->
4675 ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4679 (* Generate the server-side stubs. *)
4680 and generate_daemon_actions () =
4681 generate_header CStyle GPLv2;
4683 pr "#include <config.h>\n";
4685 pr "#include <stdio.h>\n";
4686 pr "#include <stdlib.h>\n";
4687 pr "#include <string.h>\n";
4688 pr "#include <inttypes.h>\n";
4689 pr "#include <ctype.h>\n";
4690 pr "#include <rpc/types.h>\n";
4691 pr "#include <rpc/xdr.h>\n";
4693 pr "#include \"daemon.h\"\n";
4694 pr "#include \"../src/guestfs_protocol.h\"\n";
4695 pr "#include \"actions.h\"\n";
4699 fun (name, style, _, _, _, _, _) ->
4700 (* Generate server-side stubs. *)
4701 pr "static void %s_stub (XDR *xdr_in)\n" name;
4704 match fst style with
4705 | RErr | RInt _ -> pr " int r;\n"; "-1"
4706 | RInt64 _ -> pr " int64_t r;\n"; "-1"
4707 | RBool _ -> pr " int r;\n"; "-1"
4708 | RConstString _ | RConstOptString _ ->
4709 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4710 | RString _ -> pr " char *r;\n"; "NULL"
4711 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
4712 | RStruct (_, typ) -> pr " guestfs_int_%s *r;\n" typ; "NULL"
4713 | RStructList (_, typ) -> pr " guestfs_int_%s_list *r;\n" typ; "NULL"
4715 pr " size_t size;\n";
4719 (match snd style with
4722 pr " struct guestfs_%s_args args;\n" name;
4725 (* Note we allow the string to be writable, in order to
4726 * allow device name translation. This is safe because
4727 * we can modify the string (passed from RPC).
4730 | OptString n -> pr " char *%s;\n" n
4731 | StringList n -> pr " char **%s;\n" n
4732 | Bool n -> pr " int %s;\n" n
4733 | Int n -> pr " int %s;\n" n
4734 | FileIn _ | FileOut _ -> ()
4739 (match snd style with
4742 pr " memset (&args, 0, sizeof args);\n";
4744 pr " if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4745 pr " reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4750 | String n -> pr " %s = args.%s;\n" n n
4751 | OptString n -> pr " %s = args.%s ? *args.%s : NULL;\n" n n n
4753 pr " %s = realloc (args.%s.%s_val,\n" n n n;
4754 pr " sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4755 pr " if (%s == NULL) {\n" n;
4756 pr " reply_with_perror (\"realloc\");\n";
4759 pr " %s[args.%s.%s_len] = NULL;\n" n n n;
4760 pr " args.%s.%s_val = %s;\n" n n n;
4761 | Bool n -> pr " %s = args.%s;\n" n n
4762 | Int n -> pr " %s = args.%s;\n" n n
4763 | FileIn _ | FileOut _ -> ()
4768 (* Don't want to call the impl with any FileIn or FileOut
4769 * parameters, since these go "outside" the RPC protocol.
4772 List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
4774 pr " r = do_%s " name;
4775 generate_c_call_args (fst style, args');
4778 pr " if (r == %s)\n" error_code;
4779 pr " /* do_%s has already called reply_with_error */\n" name;
4783 (* If there are any FileOut parameters, then the impl must
4784 * send its own reply.
4787 List.exists (function FileOut _ -> true | _ -> false) (snd style) in
4789 pr " /* do_%s has already sent a reply */\n" name
4791 match fst style with
4792 | RErr -> pr " reply (NULL, NULL);\n"
4793 | RInt n | RInt64 n | RBool n ->
4794 pr " struct guestfs_%s_ret ret;\n" name;
4795 pr " ret.%s = r;\n" n;
4796 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4798 | RConstString _ | RConstOptString _ ->
4799 failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4801 pr " struct guestfs_%s_ret ret;\n" name;
4802 pr " ret.%s = r;\n" n;
4803 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4806 | RStringList n | RHashtable n ->
4807 pr " struct guestfs_%s_ret ret;\n" name;
4808 pr " ret.%s.%s_len = count_strings (r);\n" n n;
4809 pr " ret.%s.%s_val = r;\n" n n;
4810 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4812 pr " free_strings (r);\n"
4814 pr " struct guestfs_%s_ret ret;\n" name;
4815 pr " ret.%s = *r;\n" n;
4816 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4818 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4820 | RStructList (n, _) ->
4821 pr " struct guestfs_%s_ret ret;\n" name;
4822 pr " ret.%s = *r;\n" n;
4823 pr " reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4825 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4828 pr " struct guestfs_%s_ret ret;\n" name;
4829 pr " ret.%s.%s_val = r;\n" n n;
4830 pr " ret.%s.%s_len = size;\n" n n;
4831 pr " reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4836 (* Free the args. *)
4837 (match snd style with
4842 pr " xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
4849 (* Dispatch function. *)
4850 pr "void dispatch_incoming_message (XDR *xdr_in)\n";
4852 pr " switch (proc_nr) {\n";
4855 fun (name, style, _, _, _, _, _) ->
4856 pr " case GUESTFS_PROC_%s:\n" (String.uppercase name);
4857 pr " %s_stub (xdr_in);\n" name;
4862 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";
4867 (* LVM columns and tokenization functions. *)
4868 (* XXX This generates crap code. We should rethink how we
4874 pr "static const char *lvm_%s_cols = \"%s\";\n"
4875 typ (String.concat "," (List.map fst cols));
4878 pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
4880 pr " char *tok, *p, *next;\n";
4884 pr " fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
4887 pr " if (!str) {\n";
4888 pr " fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
4891 pr " if (!*str || isspace (*str)) {\n";
4892 pr " fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
4897 fun (name, coltype) ->
4898 pr " if (!tok) {\n";
4899 pr " fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
4902 pr " p = strchrnul (tok, ',');\n";
4903 pr " if (*p) next = p+1; else next = NULL;\n";
4904 pr " *p = '\\0';\n";
4907 pr " r->%s = strdup (tok);\n" name;
4908 pr " if (r->%s == NULL) {\n" name;
4909 pr " perror (\"strdup\");\n";
4913 pr " for (i = j = 0; i < 32; ++j) {\n";
4914 pr " if (tok[j] == '\\0') {\n";
4915 pr " fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
4917 pr " } else if (tok[j] != '-')\n";
4918 pr " r->%s[i++] = tok[j];\n" name;
4921 pr " if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
4922 pr " fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
4926 pr " if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
4927 pr " fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
4931 pr " if (tok[0] == '\\0')\n";
4932 pr " r->%s = -1;\n" name;
4933 pr " else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
4934 pr " fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
4937 | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
4938 assert false (* can never be an LVM column *)
4940 pr " tok = next;\n";
4943 pr " if (tok != NULL) {\n";
4944 pr " fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
4951 pr "guestfs_int_lvm_%s_list *\n" typ;
4952 pr "parse_command_line_%ss (void)\n" typ;
4954 pr " char *out, *err;\n";
4955 pr " char *p, *pend;\n";
4957 pr " guestfs_int_lvm_%s_list *ret;\n" typ;
4958 pr " void *newp;\n";
4960 pr " ret = malloc (sizeof *ret);\n";
4961 pr " if (!ret) {\n";
4962 pr " reply_with_perror (\"malloc\");\n";
4963 pr " return NULL;\n";
4966 pr " ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
4967 pr " ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
4969 pr " r = command (&out, &err,\n";
4970 pr " \"/sbin/lvm\", \"%ss\",\n" typ;
4971 pr " \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
4972 pr " \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
4973 pr " if (r == -1) {\n";
4974 pr " reply_with_error (\"%%s\", err);\n";
4975 pr " free (out);\n";
4976 pr " free (err);\n";
4977 pr " free (ret);\n";
4978 pr " return NULL;\n";
4981 pr " free (err);\n";
4983 pr " /* Tokenize each line of the output. */\n";
4986 pr " while (p) {\n";
4987 pr " pend = strchr (p, '\\n'); /* Get the next line of output. */\n";
4988 pr " if (pend) {\n";
4989 pr " *pend = '\\0';\n";
4993 pr " while (*p && isspace (*p)) /* Skip any leading whitespace. */\n";
4996 pr " if (!*p) { /* Empty line? Skip it. */\n";
5001 pr " /* Allocate some space to store this next entry. */\n";
5002 pr " newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5003 pr " sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5004 pr " if (newp == NULL) {\n";
5005 pr " reply_with_perror (\"realloc\");\n";
5006 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5007 pr " free (ret);\n";
5008 pr " free (out);\n";
5009 pr " return NULL;\n";
5011 pr " ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5013 pr " /* Tokenize the next entry. */\n";
5014 pr " r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5015 pr " if (r == -1) {\n";
5016 pr " reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5017 pr " free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5018 pr " free (ret);\n";
5019 pr " free (out);\n";
5020 pr " return NULL;\n";
5027 pr " ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5029 pr " free (out);\n";
5030 pr " return ret;\n";
5033 ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5035 (* Generate a list of function names, for debugging in the daemon.. *)
5036 and generate_daemon_names () =
5037 generate_header CStyle GPLv2;
5039 pr "#include <config.h>\n";
5041 pr "#include \"daemon.h\"\n";
5044 pr "/* This array is indexed by proc_nr. See guestfs_protocol.x. */\n";
5045 pr "const char *function_names[] = {\n";
5047 fun (name, _, proc_nr, _, _, _, _) -> pr " [%d] = \"%s\",\n" proc_nr name
5051 (* Generate the tests. *)
5052 and generate_tests () =
5053 generate_header CStyle GPLv2;
5060 #include <sys/types.h>
5063 #include \"guestfs.h\"
5065 static guestfs_h *g;
5066 static int suppress_error = 0;
5068 static void print_error (guestfs_h *g, void *data, const char *msg)
5070 if (!suppress_error)
5071 fprintf (stderr, \"%%s\\n\", msg);
5074 static void print_strings (char * const * const argv)
5078 for (argc = 0; argv[argc] != NULL; ++argc)
5079 printf (\"\\t%%s\\n\", argv[argc]);
5083 static void print_table (char * const * const argv)
5087 for (i = 0; argv[i] != NULL; i += 2)
5088 printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5094 (* Generate a list of commands which are not tested anywhere. *)
5095 pr "static void no_test_warnings (void)\n";
5098 let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5100 fun (_, _, _, _, tests, _, _) ->
5101 let tests = filter_map (
5103 | (_, (Always|If _|Unless _), test) -> Some test
5104 | (_, Disabled, _) -> None
5106 let seq = List.concat (List.map seq_of_test tests) in
5107 let cmds_tested = List.map List.hd seq in
5108 List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5112 fun (name, _, _, _, _, _, _) ->
5113 if not (Hashtbl.mem hash name) then
5114 pr " fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5120 (* Generate the actual tests. Note that we generate the tests
5121 * in reverse order, deliberately, so that (in general) the
5122 * newest tests run first. This makes it quicker and easier to
5127 fun (name, _, _, _, tests, _, _) ->
5128 mapi (generate_one_test name) tests
5129 ) (List.rev all_functions) in
5130 let test_names = List.concat test_names in
5131 let nr_tests = List.length test_names in
5134 int main (int argc, char *argv[])
5138 const char *filename;
5140 int nr_tests, test_num = 0;
5142 setbuf (stdout, NULL);
5144 no_test_warnings ();
5146 g = guestfs_create ();
5148 printf (\"guestfs_create FAILED\\n\");
5152 guestfs_set_error_handler (g, print_error, NULL);
5154 guestfs_set_path (g, \"../appliance\");
5156 filename = \"test1.img\";
5157 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5162 if (lseek (fd, %d, SEEK_SET) == -1) {
5168 if (write (fd, &c, 1) == -1) {
5174 if (close (fd) == -1) {
5179 if (guestfs_add_drive (g, filename) == -1) {
5180 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5184 filename = \"test2.img\";
5185 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5190 if (lseek (fd, %d, SEEK_SET) == -1) {
5196 if (write (fd, &c, 1) == -1) {
5202 if (close (fd) == -1) {
5207 if (guestfs_add_drive (g, filename) == -1) {
5208 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5212 filename = \"test3.img\";
5213 fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5218 if (lseek (fd, %d, SEEK_SET) == -1) {
5224 if (write (fd, &c, 1) == -1) {
5230 if (close (fd) == -1) {
5235 if (guestfs_add_drive (g, filename) == -1) {
5236 printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5240 if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
5241 printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
5245 if (guestfs_launch (g) == -1) {
5246 printf (\"guestfs_launch FAILED\\n\");
5250 /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5253 if (guestfs_wait_ready (g) == -1) {
5254 printf (\"guestfs_wait_ready FAILED\\n\");
5258 /* Cancel previous alarm. */
5263 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5267 pr " test_num++;\n";
5268 pr " printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5269 pr " if (%s () == -1) {\n" test_name;
5270 pr " printf (\"%s FAILED\\n\");\n" test_name;
5276 pr " guestfs_close (g);\n";
5277 pr " unlink (\"test1.img\");\n";
5278 pr " unlink (\"test2.img\");\n";
5279 pr " unlink (\"test3.img\");\n";
5282 pr " if (failed > 0) {\n";
5283 pr " printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
5291 and generate_one_test name i (init, prereq, test) =
5292 let test_name = sprintf "test_%s_%d" name i in
5295 static int %s_skip (void)
5299 str = getenv (\"TEST_ONLY\");
5301 return strstr (str, \"%s\") == NULL;
5302 str = getenv (\"SKIP_%s\");
5303 if (str && strcmp (str, \"1\") == 0) return 1;
5304 str = getenv (\"SKIP_TEST_%s\");
5305 if (str && strcmp (str, \"1\") == 0) return 1;
5309 " test_name name (String.uppercase test_name) (String.uppercase name);
5312 | Disabled | Always -> ()
5313 | If code | Unless code ->
5314 pr "static int %s_prereq (void)\n" test_name;
5322 static int %s (void)
5325 printf (\" %%s skipped (reason: environment variable set)\\n\", \"%s\");
5329 " test_name test_name test_name;
5333 pr " printf (\" %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5335 pr " if (! %s_prereq ()) {\n" test_name;
5336 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5340 generate_one_test_body name i test_name init test;
5342 pr " if (%s_prereq ()) {\n" test_name;
5343 pr " printf (\" %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5347 generate_one_test_body name i test_name init test;
5349 generate_one_test_body name i test_name init test
5357 and generate_one_test_body name i test_name init test =
5359 | InitNone (* XXX at some point, InitNone and InitEmpty became
5360 * folded together as the same thing. Really we should
5361 * make InitNone do nothing at all, but the tests may
5362 * need to be checked to make sure this is OK.
5365 pr " /* InitNone|InitEmpty for %s */\n" test_name;
5366 List.iter (generate_test_command_call test_name)
5367 [["blockdev_setrw"; "/dev/sda"];
5371 pr " /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5372 List.iter (generate_test_command_call test_name)
5373 [["blockdev_setrw"; "/dev/sda"];
5376 ["sfdiskM"; "/dev/sda"; ","]]
5378 pr " /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5379 List.iter (generate_test_command_call test_name)
5380 [["blockdev_setrw"; "/dev/sda"];
5383 ["sfdiskM"; "/dev/sda"; ","];
5384 ["mkfs"; "ext2"; "/dev/sda1"];
5385 ["mount"; "/dev/sda1"; "/"]]
5386 | InitBasicFSonLVM ->
5387 pr " /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5389 List.iter (generate_test_command_call test_name)
5390 [["blockdev_setrw"; "/dev/sda"];
5393 ["sfdiskM"; "/dev/sda"; ","];
5394 ["pvcreate"; "/dev/sda1"];
5395 ["vgcreate"; "VG"; "/dev/sda1"];
5396 ["lvcreate"; "LV"; "VG"; "8"];
5397 ["mkfs"; "ext2"; "/dev/VG/LV"];
5398 ["mount"; "/dev/VG/LV"; "/"]]
5400 pr " /* InitSquashFS for %s */\n" test_name;
5401 List.iter (generate_test_command_call test_name)
5402 [["blockdev_setrw"; "/dev/sda"];
5405 ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
5408 let get_seq_last = function
5410 failwithf "%s: you cannot use [] (empty list) when expecting a command"
5413 let seq = List.rev seq in
5414 List.rev (List.tl seq), List.hd seq
5419 pr " /* TestRun for %s (%d) */\n" name i;
5420 List.iter (generate_test_command_call test_name) seq
5421 | TestOutput (seq, expected) ->
5422 pr " /* TestOutput for %s (%d) */\n" name i;
5423 pr " const char *expected = \"%s\";\n" (c_quote expected);
5424 let seq, last = get_seq_last seq in
5426 pr " if (strcmp (r, expected) != 0) {\n";
5427 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5431 List.iter (generate_test_command_call test_name) seq;
5432 generate_test_command_call ~test test_name last
5433 | TestOutputList (seq, expected) ->
5434 pr " /* TestOutputList for %s (%d) */\n" name i;
5435 let seq, last = get_seq_last seq in
5439 pr " if (!r[%d]) {\n" i;
5440 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5441 pr " print_strings (r);\n";
5445 pr " const char *expected = \"%s\";\n" (c_quote str);
5446 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5447 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5452 pr " if (r[%d] != NULL) {\n" (List.length expected);
5453 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5455 pr " print_strings (r);\n";
5459 List.iter (generate_test_command_call test_name) seq;
5460 generate_test_command_call ~test test_name last
5461 | TestOutputListOfDevices (seq, expected) ->
5462 pr " /* TestOutputListOfDevices for %s (%d) */\n" name i;
5463 let seq, last = get_seq_last seq in
5467 pr " if (!r[%d]) {\n" i;
5468 pr " fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5469 pr " print_strings (r);\n";
5473 pr " const char *expected = \"%s\";\n" (c_quote str);
5474 pr " r[%d][5] = 's';\n" i;
5475 pr " if (strcmp (r[%d], expected) != 0) {\n" i;
5476 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5481 pr " if (r[%d] != NULL) {\n" (List.length expected);
5482 pr " fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5484 pr " print_strings (r);\n";
5488 List.iter (generate_test_command_call test_name) seq;
5489 generate_test_command_call ~test test_name last
5490 | TestOutputInt (seq, expected) ->
5491 pr " /* TestOutputInt for %s (%d) */\n" name i;
5492 let seq, last = get_seq_last seq in
5494 pr " if (r != %d) {\n" expected;
5495 pr " fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5501 List.iter (generate_test_command_call test_name) seq;
5502 generate_test_command_call ~test test_name last
5503 | TestOutputIntOp (seq, op, expected) ->
5504 pr " /* TestOutputIntOp for %s (%d) */\n" name i;
5505 let seq, last = get_seq_last seq in
5507 pr " if (! (r %s %d)) {\n" op expected;
5508 pr " fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5509 test_name op expected;
5514 List.iter (generate_test_command_call test_name) seq;
5515 generate_test_command_call ~test test_name last
5516 | TestOutputTrue seq ->
5517 pr " /* TestOutputTrue for %s (%d) */\n" name i;
5518 let seq, last = get_seq_last seq in
5521 pr " fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5526 List.iter (generate_test_command_call test_name) seq;
5527 generate_test_command_call ~test test_name last
5528 | TestOutputFalse seq ->
5529 pr " /* TestOutputFalse for %s (%d) */\n" name i;
5530 let seq, last = get_seq_last seq in
5533 pr " fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5538 List.iter (generate_test_command_call test_name) seq;
5539 generate_test_command_call ~test test_name last
5540 | TestOutputLength (seq, expected) ->
5541 pr " /* TestOutputLength for %s (%d) */\n" name i;
5542 let seq, last = get_seq_last seq in
5545 pr " for (j = 0; j < %d; ++j)\n" expected;
5546 pr " if (r[j] == NULL) {\n";
5547 pr " fprintf (stderr, \"%s: short list returned\\n\");\n"
5549 pr " print_strings (r);\n";
5552 pr " if (r[j] != NULL) {\n";
5553 pr " fprintf (stderr, \"%s: long list returned\\n\");\n"
5555 pr " print_strings (r);\n";
5559 List.iter (generate_test_command_call test_name) seq;
5560 generate_test_command_call ~test test_name last
5561 | TestOutputBuffer (seq, expected) ->
5562 pr " /* TestOutputBuffer for %s (%d) */\n" name i;
5563 pr " const char *expected = \"%s\";\n" (c_quote expected);
5564 let seq, last = get_seq_last seq in
5565 let len = String.length expected in
5567 pr " if (size != %d) {\n" len;
5568 pr " fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5571 pr " if (strncmp (r, expected, size) != 0) {\n";
5572 pr " fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5576 List.iter (generate_test_command_call test_name) seq;
5577 generate_test_command_call ~test test_name last
5578 | TestOutputStruct (seq, checks) ->
5579 pr " /* TestOutputStruct for %s (%d) */\n" name i;
5580 let seq, last = get_seq_last seq in
5584 | CompareWithInt (field, expected) ->
5585 pr " if (r->%s != %d) {\n" field expected;
5586 pr " fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5587 test_name field expected;
5588 pr " (int) r->%s);\n" field;
5591 | CompareWithIntOp (field, op, expected) ->
5592 pr " if (!(r->%s %s %d)) {\n" field op expected;
5593 pr " fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5594 test_name field op expected;
5595 pr " (int) r->%s);\n" field;
5598 | CompareWithString (field, expected) ->
5599 pr " if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5600 pr " fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5601 test_name field expected;
5602 pr " r->%s);\n" field;
5605 | CompareFieldsIntEq (field1, field2) ->
5606 pr " if (r->%s != r->%s) {\n" field1 field2;
5607 pr " fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5608 test_name field1 field2;
5609 pr " (int) r->%s, (int) r->%s);\n" field1 field2;
5612 | CompareFieldsStrEq (field1, field2) ->
5613 pr " if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5614 pr " fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5615 test_name field1 field2;
5616 pr " r->%s, r->%s);\n" field1 field2;
5621 List.iter (generate_test_command_call test_name) seq;
5622 generate_test_command_call ~test test_name last
5623 | TestLastFail seq ->
5624 pr " /* TestLastFail for %s (%d) */\n" name i;
5625 let seq, last = get_seq_last seq in
5626 List.iter (generate_test_command_call test_name) seq;
5627 generate_test_command_call test_name ~expect_error:true last
5629 (* Generate the code to run a command, leaving the result in 'r'.
5630 * If you expect to get an error then you should set expect_error:true.
5632 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5634 | [] -> assert false
5636 (* Look up the command to find out what args/ret it has. *)
5639 let _, style, _, _, _, _, _ =
5640 List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5643 failwithf "%s: in test, command %s was not found" test_name name in
5645 if List.length (snd style) <> List.length args then
5646 failwithf "%s: in test, wrong number of args given to %s"
5653 | OptString n, "NULL" -> ()
5655 | OptString n, arg ->
5656 pr " const char *%s = \"%s\";\n" n (c_quote arg);
5659 | FileIn _, _ | FileOut _, _ -> ()
5660 | StringList n, arg ->
5661 let strs = string_split " " arg in
5664 pr " const char *%s_%d = \"%s\";\n" n i (c_quote str);
5666 pr " const char *%s[] = {\n" n;
5668 fun i _ -> pr " %s_%d,\n" n i
5672 ) (List.combine (snd style) args);
5675 match fst style with
5676 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
5677 | RInt64 _ -> pr " int64_t r;\n"; "-1"
5678 | RConstString _ | RConstOptString _ ->
5679 pr " const char *r;\n"; "NULL"
5680 | RString _ -> pr " char *r;\n"; "NULL"
5681 | RStringList _ | RHashtable _ ->
5685 | RStruct (_, typ) ->
5686 pr " struct guestfs_%s *r;\n" typ; "NULL"
5687 | RStructList (_, typ) ->
5688 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
5691 pr " size_t size;\n";
5694 pr " suppress_error = %d;\n" (if expect_error then 1 else 0);
5695 pr " r = guestfs_%s (g" name;
5697 (* Generate the parameters. *)
5700 | OptString _, "NULL" -> pr ", NULL"
5704 | FileIn _, arg | FileOut _, arg ->
5705 pr ", \"%s\"" (c_quote arg)
5706 | StringList n, _ ->
5710 try int_of_string arg
5711 with Failure "int_of_string" ->
5712 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5715 let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5716 ) (List.combine (snd style) args);
5718 (match fst style with
5719 | RBufferOut _ -> pr ", &size"
5725 if not expect_error then
5726 pr " if (r == %s)\n" error_code
5728 pr " if (r != %s)\n" error_code;
5731 (* Insert the test code. *)
5737 (match fst style with
5738 | RErr | RInt _ | RInt64 _ | RBool _
5739 | RConstString _ | RConstOptString _ -> ()
5740 | RString _ | RBufferOut _ -> pr " free (r);\n"
5741 | RStringList _ | RHashtable _ ->
5742 pr " for (i = 0; r[i] != NULL; ++i)\n";
5743 pr " free (r[i]);\n";
5745 | RStruct (_, typ) ->
5746 pr " guestfs_free_%s (r);\n" typ
5747 | RStructList (_, typ) ->
5748 pr " guestfs_free_%s_list (r);\n" typ
5754 let str = replace_str str "\r" "\\r" in
5755 let str = replace_str str "\n" "\\n" in
5756 let str = replace_str str "\t" "\\t" in
5757 let str = replace_str str "\000" "\\0" in
5760 (* Generate a lot of different functions for guestfish. *)
5761 and generate_fish_cmds () =
5762 generate_header CStyle GPLv2;
5766 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5768 let all_functions_sorted =
5770 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5771 ) all_functions_sorted in
5773 pr "#include <stdio.h>\n";
5774 pr "#include <stdlib.h>\n";
5775 pr "#include <string.h>\n";
5776 pr "#include <inttypes.h>\n";
5777 pr "#include <ctype.h>\n";
5779 pr "#include <guestfs.h>\n";
5780 pr "#include \"fish.h\"\n";
5783 (* list_commands function, which implements guestfish -h *)
5784 pr "void list_commands (void)\n";
5786 pr " printf (\" %%-16s %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
5787 pr " list_builtin_commands ();\n";
5789 fun (name, _, _, flags, _, shortdesc, _) ->
5790 let name = replace_char name '_' '-' in
5791 pr " printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
5793 ) all_functions_sorted;
5794 pr " printf (\" %%s\\n\",";
5795 pr " _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
5799 (* display_command function, which implements guestfish -h cmd *)
5800 pr "void display_command (const char *cmd)\n";
5803 fun (name, style, _, flags, _, shortdesc, longdesc) ->
5804 let name2 = replace_char name '_' '-' in
5806 try find_map (function FishAlias n -> Some n | _ -> None) flags
5807 with Not_found -> name in
5808 let longdesc = replace_str longdesc "C<guestfs_" "C<" in
5810 match snd style with
5814 name2 (String.concat "> <" (List.map name_of_argt args)) in
5817 if List.mem ProtocolLimitWarning flags then
5818 ("\n\n" ^ protocol_limit_warning)
5821 (* For DangerWillRobinson commands, we should probably have
5822 * guestfish prompt before allowing you to use them (especially
5823 * in interactive mode). XXX
5827 if List.mem DangerWillRobinson flags then
5828 ("\n\n" ^ danger_will_robinson)
5833 match deprecation_notice flags with
5835 | Some txt -> "\n\n" ^ txt in
5837 let describe_alias =
5838 if name <> alias then
5839 sprintf "\n\nYou can use '%s' as an alias for this command." alias
5843 pr "strcasecmp (cmd, \"%s\") == 0" name;
5844 if name <> name2 then
5845 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
5846 if name <> alias then
5847 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
5849 pr " pod2text (\"%s\", _(\"%s\"), %S);\n"
5851 (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
5854 pr " display_builtin_command (cmd);\n";
5858 (* print_* functions *)
5862 List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
5864 pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
5873 pr " printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
5875 pr " printf (\"%s: \");\n" name;
5876 pr " for (i = 0; i < 32; ++i)\n";
5877 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5878 pr " printf (\"\\n\");\n"
5880 pr " printf (\"%%s%s: \", indent);\n" name;
5881 pr " for (i = 0; i < %s->%s_len; ++i)\n" typ name;
5882 pr " if (isprint (%s->%s[i]))\n" typ name;
5883 pr " printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5885 pr " printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
5886 pr " printf (\"\\n\");\n"
5887 | name, (FUInt64|FBytes) ->
5888 pr " printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
5891 pr " printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
5894 pr " printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
5897 pr " printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
5900 pr " printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
5902 | name, FOptPercent ->
5903 pr " if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
5904 typ name name typ name;
5905 pr " else printf (\"%%s%s: \\n\", indent);\n" name
5909 pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
5911 pr " print_%s_indent (%s, \"\");\n" typ typ;
5914 pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
5919 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
5920 pr " printf (\"[%%d] = {\\n\", i);\n";
5921 pr " print_%s_indent (&%ss->val[i], \" \");\n" typ typ;
5922 pr " printf (\"}\\n\");\n";
5928 (* run_<action> actions *)
5930 fun (name, style, _, flags, _, _, _) ->
5931 pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
5933 (match fst style with
5936 | RBool _ -> pr " int r;\n"
5937 | RInt64 _ -> pr " int64_t r;\n"
5938 | RConstString _ | RConstOptString _ -> pr " const char *r;\n"
5939 | RString _ -> pr " char *r;\n"
5940 | RStringList _ | RHashtable _ -> pr " char **r;\n"
5941 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ
5942 | RStructList (_, typ) -> pr " struct guestfs_%s_list *r;\n" typ
5945 pr " size_t size;\n";
5952 | FileOut n -> pr " const char *%s;\n" n
5953 | StringList n -> pr " char **%s;\n" n
5954 | Bool n -> pr " int %s;\n" n
5955 | Int n -> pr " int %s;\n" n
5958 (* Check and convert parameters. *)
5959 let argc_expected = List.length (snd style) in
5960 pr " if (argc != %d) {\n" argc_expected;
5961 pr " fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
5963 pr " fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
5969 | String name -> pr " %s = argv[%d];\n" name i
5971 pr " %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
5974 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
5977 pr " %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
5979 | StringList name ->
5980 pr " %s = parse_string_list (argv[%d]);\n" name i
5982 pr " %s = is_true (argv[%d]) ? 1 : 0;\n" name i
5984 pr " %s = atoi (argv[%d]);\n" name i
5987 (* Call C API function. *)
5989 try find_map (function FishAction n -> Some n | _ -> None) flags
5990 with Not_found -> sprintf "guestfs_%s" name in
5992 generate_c_call_args ~handle:"g" style;
5995 (* Check return value for errors and display command results. *)
5996 (match fst style with
5997 | RErr -> pr " return r;\n"
5999 pr " if (r == -1) return -1;\n";
6000 pr " printf (\"%%d\\n\", r);\n";
6003 pr " if (r == -1) return -1;\n";
6004 pr " printf (\"%%\" PRIi64 \"\\n\", r);\n";
6007 pr " if (r == -1) return -1;\n";
6008 pr " if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6011 pr " if (r == NULL) return -1;\n";
6012 pr " printf (\"%%s\\n\", r);\n";
6014 | RConstOptString _ ->
6015 pr " printf (\"%%s\\n\", r ? : \"(null)\");\n";
6018 pr " if (r == NULL) return -1;\n";
6019 pr " printf (\"%%s\\n\", r);\n";
6023 pr " if (r == NULL) return -1;\n";
6024 pr " print_strings (r);\n";
6025 pr " free_strings (r);\n";
6027 | RStruct (_, typ) ->
6028 pr " if (r == NULL) return -1;\n";
6029 pr " print_%s (r);\n" typ;
6030 pr " guestfs_free_%s (r);\n" typ;
6032 | RStructList (_, typ) ->
6033 pr " if (r == NULL) return -1;\n";
6034 pr " print_%s_list (r);\n" typ;
6035 pr " guestfs_free_%s_list (r);\n" typ;
6038 pr " if (r == NULL) return -1;\n";
6039 pr " print_table (r);\n";
6040 pr " free_strings (r);\n";
6043 pr " if (r == NULL) return -1;\n";
6044 pr " fwrite (r, size, 1, stdout);\n";
6052 (* run_action function *)
6053 pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6056 fun (name, _, _, flags, _, _, _) ->
6057 let name2 = replace_char name '_' '-' in
6059 try find_map (function FishAlias n -> Some n | _ -> None) flags
6060 with Not_found -> name in
6062 pr "strcasecmp (cmd, \"%s\") == 0" name;
6063 if name <> name2 then
6064 pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6065 if name <> alias then
6066 pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6068 pr " return run_%s (cmd, argc, argv);\n" name;
6072 pr " fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6079 (* Readline completion for guestfish. *)
6080 and generate_fish_completion () =
6081 generate_header CStyle GPLv2;
6085 fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6095 #ifdef HAVE_LIBREADLINE
6096 #include <readline/readline.h>
6101 #ifdef HAVE_LIBREADLINE
6103 static const char *const commands[] = {
6104 BUILTIN_COMMANDS_FOR_COMPLETION,
6107 (* Get the commands, including the aliases. They don't need to be
6108 * sorted - the generator() function just does a dumb linear search.
6112 fun (name, _, _, flags, _, _, _) ->
6113 let name2 = replace_char name '_' '-' in
6115 try find_map (function FishAlias n -> Some n | _ -> None) flags
6116 with Not_found -> name in
6118 if name <> alias then [name2; alias] else [name2]
6120 let commands = List.flatten commands in
6122 List.iter (pr " \"%s\",\n") commands;
6128 generator (const char *text, int state)
6130 static int index, len;
6135 len = strlen (text);
6138 rl_attempted_completion_over = 1;
6140 while ((name = commands[index]) != NULL) {
6142 if (strncasecmp (name, text, len) == 0)
6143 return strdup (name);
6149 #endif /* HAVE_LIBREADLINE */
6151 char **do_completion (const char *text, int start, int end)
6153 char **matches = NULL;
6155 #ifdef HAVE_LIBREADLINE
6156 rl_completion_append_character = ' ';
6159 matches = rl_completion_matches (text, generator);
6160 else if (complete_dest_paths)
6161 matches = rl_completion_matches (text, complete_dest_paths_generator);
6168 (* Generate the POD documentation for guestfish. *)
6169 and generate_fish_actions_pod () =
6170 let all_functions_sorted =
6172 fun (_, _, _, flags, _, _, _) ->
6173 not (List.mem NotInFish flags || List.mem NotInDocs flags)
6174 ) all_functions_sorted in
6176 let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6179 fun (name, style, _, flags, _, _, longdesc) ->
6181 Str.global_substitute rex (
6184 try Str.matched_group 1 s
6186 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6187 "C<" ^ replace_char sub '_' '-' ^ ">"
6189 let name = replace_char name '_' '-' in
6191 try find_map (function FishAlias n -> Some n | _ -> None) flags
6192 with Not_found -> name in
6194 pr "=head2 %s" name;
6195 if name <> alias then
6202 | String n -> pr " %s" n
6203 | OptString n -> pr " %s" n
6204 | StringList n -> pr " '%s ...'" n
6205 | Bool _ -> pr " true|false"
6206 | Int n -> pr " %s" n
6207 | FileIn n | FileOut n -> pr " (%s|-)" n
6211 pr "%s\n\n" longdesc;
6213 if List.exists (function FileIn _ | FileOut _ -> true
6214 | _ -> false) (snd style) then
6215 pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6217 if List.mem ProtocolLimitWarning flags then
6218 pr "%s\n\n" protocol_limit_warning;
6220 if List.mem DangerWillRobinson flags then
6221 pr "%s\n\n" danger_will_robinson;
6223 match deprecation_notice flags with
6225 | Some txt -> pr "%s\n\n" txt
6226 ) all_functions_sorted
6228 (* Generate a C function prototype. *)
6229 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6230 ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6232 ?handle name style =
6233 if extern then pr "extern ";
6234 if static then pr "static ";
6235 (match fst style with
6237 | RInt _ -> pr "int "
6238 | RInt64 _ -> pr "int64_t "
6239 | RBool _ -> pr "int "
6240 | RConstString _ | RConstOptString _ -> pr "const char *"
6241 | RString _ | RBufferOut _ -> pr "char *"
6242 | RStringList _ | RHashtable _ -> pr "char **"
6243 | RStruct (_, typ) ->
6244 if not in_daemon then pr "struct guestfs_%s *" typ
6245 else pr "guestfs_int_%s *" typ
6246 | RStructList (_, typ) ->
6247 if not in_daemon then pr "struct guestfs_%s_list *" typ
6248 else pr "guestfs_int_%s_list *" typ
6250 let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6251 pr "%s%s (" prefix name;
6252 if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6255 let comma = ref false in
6258 | Some handle -> pr "guestfs_h *%s" handle; comma := true
6262 if single_line then pr ", " else pr ",\n\t\t"
6271 if not in_daemon then pr "const char *%s" n
6272 else pr "char *%s" n
6275 if not in_daemon then pr "char * const* const %s" n
6276 else pr "char **%s" n
6277 | Bool n -> next (); pr "int %s" n
6278 | Int n -> next (); pr "int %s" n
6281 if not in_daemon then (next (); pr "const char *%s" n)
6283 if is_RBufferOut then (next (); pr "size_t *size_r");
6286 if semicolon then pr ";";
6287 if newline then pr "\n"
6289 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6290 and generate_c_call_args ?handle ?(decl = false) style =
6292 let comma = ref false in
6294 if !comma then pr ", ";
6299 | Some handle -> pr "%s" handle; comma := true
6304 pr "%s" (name_of_argt arg)
6306 (* For RBufferOut calls, add implicit &size parameter. *)
6308 match fst style with
6316 (* Generate the OCaml bindings interface. *)
6317 and generate_ocaml_mli () =
6318 generate_header OCamlStyle LGPLv2;
6321 (** For API documentation you should refer to the C API
6322 in the guestfs(3) manual page. The OCaml API uses almost
6323 exactly the same calls. *)
6326 (** A [guestfs_h] handle. *)
6328 exception Error of string
6329 (** This exception is raised when there is an error. *)
6331 val create : unit -> t
6333 val close : t -> unit
6334 (** Handles are closed by the garbage collector when they become
6335 unreferenced, but callers can also call this in order to
6336 provide predictable cleanup. *)
6339 generate_ocaml_structure_decls ();
6343 fun (name, style, _, _, _, shortdesc, _) ->
6344 generate_ocaml_prototype name style;
6345 pr "(** %s *)\n" shortdesc;
6349 (* Generate the OCaml bindings implementation. *)
6350 and generate_ocaml_ml () =
6351 generate_header OCamlStyle LGPLv2;
6355 exception Error of string
6356 external create : unit -> t = \"ocaml_guestfs_create\"
6357 external close : t -> unit = \"ocaml_guestfs_close\"
6360 Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6364 generate_ocaml_structure_decls ();
6368 fun (name, style, _, _, _, shortdesc, _) ->
6369 generate_ocaml_prototype ~is_external:true name style;
6372 (* Generate the OCaml bindings C implementation. *)
6373 and generate_ocaml_c () =
6374 generate_header CStyle LGPLv2;
6381 #include <caml/config.h>
6382 #include <caml/alloc.h>
6383 #include <caml/callback.h>
6384 #include <caml/fail.h>
6385 #include <caml/memory.h>
6386 #include <caml/mlvalues.h>
6387 #include <caml/signals.h>
6389 #include <guestfs.h>
6391 #include \"guestfs_c.h\"
6393 /* Copy a hashtable of string pairs into an assoc-list. We return
6394 * the list in reverse order, but hashtables aren't supposed to be
6397 static CAMLprim value
6398 copy_table (char * const * argv)
6401 CAMLlocal5 (rv, pairv, kv, vv, cons);
6405 for (i = 0; argv[i] != NULL; i += 2) {
6406 kv = caml_copy_string (argv[i]);
6407 vv = caml_copy_string (argv[i+1]);
6408 pairv = caml_alloc (2, 0);
6409 Store_field (pairv, 0, kv);
6410 Store_field (pairv, 1, vv);
6411 cons = caml_alloc (2, 0);
6412 Store_field (cons, 1, rv);
6414 Store_field (cons, 0, pairv);
6422 (* Struct copy functions. *)
6425 let has_optpercent_col =
6426 List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6428 pr "static CAMLprim value\n";
6429 pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6431 pr " CAMLparam0 ();\n";
6432 if has_optpercent_col then
6433 pr " CAMLlocal3 (rv, v, v2);\n"
6435 pr " CAMLlocal2 (rv, v);\n";
6437 pr " rv = caml_alloc (%d, 0);\n" (List.length cols);
6442 pr " v = caml_copy_string (%s->%s);\n" typ name
6444 pr " v = caml_alloc_string (%s->%s_len);\n" typ name;
6445 pr " memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6448 pr " v = caml_alloc_string (32);\n";
6449 pr " memcpy (String_val (v), %s->%s, 32);\n" typ name
6450 | name, (FBytes|FInt64|FUInt64) ->
6451 pr " v = caml_copy_int64 (%s->%s);\n" typ name
6452 | name, (FInt32|FUInt32) ->
6453 pr " v = caml_copy_int32 (%s->%s);\n" typ name
6454 | name, FOptPercent ->
6455 pr " if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6456 pr " v2 = caml_copy_double (%s->%s);\n" typ name;
6457 pr " v = caml_alloc (1, 0);\n";
6458 pr " Store_field (v, 0, v2);\n";
6459 pr " } else /* None */\n";
6460 pr " v = Val_int (0);\n";
6462 pr " v = Val_int (%s->%s);\n" typ name
6464 pr " Store_field (rv, %d, v);\n" i
6466 pr " CAMLreturn (rv);\n";
6470 pr "static CAMLprim value\n";
6471 pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
6474 pr " CAMLparam0 ();\n";
6475 pr " CAMLlocal2 (rv, v);\n";
6478 pr " if (%ss->len == 0)\n" typ;
6479 pr " CAMLreturn (Atom (0));\n";
6481 pr " rv = caml_alloc (%ss->len, 0);\n" typ;
6482 pr " for (i = 0; i < %ss->len; ++i) {\n" typ;
6483 pr " v = copy_%s (&%ss->val[i]);\n" typ typ;
6484 pr " caml_modify (&Field (rv, i), v);\n";
6486 pr " CAMLreturn (rv);\n";
6494 fun (name, style, _, _, _, _, _) ->
6496 "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6498 let needs_extra_vs =
6499 match fst style with RConstOptString _ -> true | _ -> false in
6501 pr "CAMLprim value\n";
6502 pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6503 List.iter (pr ", value %s") (List.tl params);
6508 | [p1; p2; p3; p4; p5] ->
6509 pr " CAMLparam5 (%s);\n" (String.concat ", " params)
6510 | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6511 pr " CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6512 pr " CAMLxparam%d (%s);\n"
6513 (List.length rest) (String.concat ", " rest)
6515 pr " CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6517 if not needs_extra_vs then
6518 pr " CAMLlocal1 (rv);\n"
6520 pr " CAMLlocal3 (rv, v, v2);\n";
6523 pr " guestfs_h *g = Guestfs_val (gv);\n";
6524 pr " if (g == NULL)\n";
6525 pr " caml_failwith (\"%s: used handle after closing it\");\n" name;
6533 pr " const char *%s = String_val (%sv);\n" n n
6535 pr " const char *%s =\n" n;
6536 pr " %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6539 pr " char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6541 pr " int %s = Bool_val (%sv);\n" n n
6543 pr " int %s = Int_val (%sv);\n" n n
6546 match fst style with
6547 | RErr -> pr " int r;\n"; "-1"
6548 | RInt _ -> pr " int r;\n"; "-1"
6549 | RInt64 _ -> pr " int64_t r;\n"; "-1"
6550 | RBool _ -> pr " int r;\n"; "-1"
6551 | RConstString _ | RConstOptString _ ->
6552 pr " const char *r;\n"; "NULL"
6553 | RString _ -> pr " char *r;\n"; "NULL"
6558 | RStruct (_, typ) ->
6559 pr " struct guestfs_%s *r;\n" typ; "NULL"
6560 | RStructList (_, typ) ->
6561 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
6568 pr " size_t size;\n";
6572 pr " caml_enter_blocking_section ();\n";
6573 pr " r = guestfs_%s " name;
6574 generate_c_call_args ~handle:"g" style;
6576 pr " caml_leave_blocking_section ();\n";
6581 pr " ocaml_guestfs_free_strings (%s);\n" n;
6582 | String _ | OptString _ | Bool _ | Int _ | FileIn _ | FileOut _ -> ()
6585 pr " if (r == %s)\n" error_code;
6586 pr " ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6589 (match fst style with
6590 | RErr -> pr " rv = Val_unit;\n"
6591 | RInt _ -> pr " rv = Val_int (r);\n"
6593 pr " rv = caml_copy_int64 (r);\n"
6594 | RBool _ -> pr " rv = Val_bool (r);\n"
6596 pr " rv = caml_copy_string (r);\n"
6597 | RConstOptString _ ->
6598 pr " if (r) { /* Some string */\n";
6599 pr " v = caml_alloc (1, 0);\n";
6600 pr " v2 = caml_copy_string (r);\n";
6601 pr " Store_field (v, 0, v2);\n";
6602 pr " } else /* None */\n";
6603 pr " v = Val_int (0);\n";
6605 pr " rv = caml_copy_string (r);\n";
6608 pr " rv = caml_copy_string_array ((const char **) r);\n";
6609 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6611 | RStruct (_, typ) ->
6612 pr " rv = copy_%s (r);\n" typ;
6613 pr " guestfs_free_%s (r);\n" typ;
6614 | RStructList (_, typ) ->
6615 pr " rv = copy_%s_list (r);\n" typ;
6616 pr " guestfs_free_%s_list (r);\n" typ;
6618 pr " rv = copy_table (r);\n";
6619 pr " for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6622 pr " rv = caml_alloc_string (size);\n";
6623 pr " memcpy (String_val (rv), r, size);\n";
6626 pr " CAMLreturn (rv);\n";
6630 if List.length params > 5 then (
6631 pr "CAMLprim value\n";
6632 pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6634 pr " return ocaml_guestfs_%s (argv[0]" name;
6635 iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6642 and generate_ocaml_structure_decls () =
6645 pr "type %s = {\n" typ;
6648 | name, FString -> pr " %s : string;\n" name
6649 | name, FBuffer -> pr " %s : string;\n" name
6650 | name, FUUID -> pr " %s : string;\n" name
6651 | name, (FBytes|FInt64|FUInt64) -> pr " %s : int64;\n" name
6652 | name, (FInt32|FUInt32) -> pr " %s : int32;\n" name
6653 | name, FChar -> pr " %s : char;\n" name
6654 | name, FOptPercent -> pr " %s : float option;\n" name
6660 and generate_ocaml_prototype ?(is_external = false) name style =
6661 if is_external then pr "external " else pr "val ";
6662 pr "%s : t -> " name;
6665 | String _ | FileIn _ | FileOut _ -> pr "string -> "
6666 | OptString _ -> pr "string option -> "
6667 | StringList _ -> pr "string array -> "
6668 | Bool _ -> pr "bool -> "
6669 | Int _ -> pr "int -> "
6671 (match fst style with
6672 | RErr -> pr "unit" (* all errors are turned into exceptions *)
6673 | RInt _ -> pr "int"
6674 | RInt64 _ -> pr "int64"
6675 | RBool _ -> pr "bool"
6676 | RConstString _ -> pr "string"
6677 | RConstOptString _ -> pr "string option"
6678 | RString _ | RBufferOut _ -> pr "string"
6679 | RStringList _ -> pr "string array"
6680 | RStruct (_, typ) -> pr "%s" typ
6681 | RStructList (_, typ) -> pr "%s array" typ
6682 | RHashtable _ -> pr "(string * string) list"
6684 if is_external then (
6686 if List.length (snd style) + 1 > 5 then
6687 pr "\"ocaml_guestfs_%s_byte\" " name;
6688 pr "\"ocaml_guestfs_%s\"" name
6692 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
6693 and generate_perl_xs () =
6694 generate_header CStyle LGPLv2;
6697 #include \"EXTERN.h\"
6701 #include <guestfs.h>
6704 #define PRId64 \"lld\"
6708 my_newSVll(long long val) {
6709 #ifdef USE_64_BIT_ALL
6710 return newSViv(val);
6714 len = snprintf(buf, 100, \"%%\" PRId64, val);
6715 return newSVpv(buf, len);
6720 #define PRIu64 \"llu\"
6724 my_newSVull(unsigned long long val) {
6725 #ifdef USE_64_BIT_ALL
6726 return newSVuv(val);
6730 len = snprintf(buf, 100, \"%%\" PRIu64, val);
6731 return newSVpv(buf, len);
6735 /* http://www.perlmonks.org/?node_id=680842 */
6737 XS_unpack_charPtrPtr (SV *arg) {
6742 if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
6743 croak (\"array reference expected\");
6745 av = (AV *)SvRV (arg);
6746 ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
6748 croak (\"malloc failed\");
6750 for (i = 0; i <= av_len (av); i++) {
6751 SV **elem = av_fetch (av, i, 0);
6753 if (!elem || !*elem)
6754 croak (\"missing element in list\");
6756 ret[i] = SvPV_nolen (*elem);
6764 MODULE = Sys::Guestfs PACKAGE = Sys::Guestfs
6771 RETVAL = guestfs_create ();
6773 croak (\"could not create guestfs handle\");
6774 guestfs_set_error_handler (RETVAL, NULL, NULL);
6787 fun (name, style, _, _, _, _, _) ->
6788 (match fst style with
6789 | RErr -> pr "void\n"
6790 | RInt _ -> pr "SV *\n"
6791 | RInt64 _ -> pr "SV *\n"
6792 | RBool _ -> pr "SV *\n"
6793 | RConstString _ -> pr "SV *\n"
6794 | RConstOptString _ -> pr "SV *\n"
6795 | RString _ -> pr "SV *\n"
6796 | RBufferOut _ -> pr "SV *\n"
6798 | RStruct _ | RStructList _
6800 pr "void\n" (* all lists returned implictly on the stack *)
6802 (* Call and arguments. *)
6804 generate_c_call_args ~handle:"g" ~decl:true style;
6806 pr " guestfs_h *g;\n";
6810 | String n | FileIn n | FileOut n -> pr " char *%s;\n" n
6812 (* http://www.perlmonks.org/?node_id=554277
6813 * Note that the implicit handle argument means we have
6814 * to add 1 to the ST(x) operator.
6816 pr " char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
6817 | StringList n -> pr " char **%s;\n" n
6818 | Bool n -> pr " int %s;\n" n
6819 | Int n -> pr " int %s;\n" n
6822 let do_cleanups () =
6825 | String _ | OptString _ | Bool _ | Int _
6826 | FileIn _ | FileOut _ -> ()
6827 | StringList n -> pr " free (%s);\n" n
6832 (match fst style with
6837 pr " r = guestfs_%s " name;
6838 generate_c_call_args ~handle:"g" style;
6841 pr " if (r == -1)\n";
6842 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6848 pr " %s = guestfs_%s " n name;
6849 generate_c_call_args ~handle:"g" style;
6852 pr " if (%s == -1)\n" n;
6853 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6854 pr " RETVAL = newSViv (%s);\n" n;
6859 pr " int64_t %s;\n" n;
6861 pr " %s = guestfs_%s " n name;
6862 generate_c_call_args ~handle:"g" style;
6865 pr " if (%s == -1)\n" n;
6866 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6867 pr " RETVAL = my_newSVll (%s);\n" n;
6872 pr " const char *%s;\n" n;
6874 pr " %s = guestfs_%s " n name;
6875 generate_c_call_args ~handle:"g" style;
6878 pr " if (%s == NULL)\n" n;
6879 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6880 pr " RETVAL = newSVpv (%s, 0);\n" n;
6883 | RConstOptString n ->
6885 pr " const char *%s;\n" n;
6887 pr " %s = guestfs_%s " n name;
6888 generate_c_call_args ~handle:"g" style;
6891 pr " if (%s == NULL)\n" n;
6892 pr " RETVAL = &PL_sv_undef;\n";
6894 pr " RETVAL = newSVpv (%s, 0);\n" n;
6899 pr " char *%s;\n" n;
6901 pr " %s = guestfs_%s " n name;
6902 generate_c_call_args ~handle:"g" style;
6905 pr " if (%s == NULL)\n" n;
6906 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6907 pr " RETVAL = newSVpv (%s, 0);\n" n;
6908 pr " free (%s);\n" n;
6911 | RStringList n | RHashtable n ->
6913 pr " char **%s;\n" n;
6916 pr " %s = guestfs_%s " n name;
6917 generate_c_call_args ~handle:"g" style;
6920 pr " if (%s == NULL)\n" n;
6921 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6922 pr " for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
6923 pr " EXTEND (SP, n);\n";
6924 pr " for (i = 0; i < n; ++i) {\n";
6925 pr " PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
6926 pr " free (%s[i]);\n" n;
6928 pr " free (%s);\n" n;
6929 | RStruct (n, typ) ->
6930 let cols = cols_of_struct typ in
6931 generate_perl_struct_code typ cols name style n do_cleanups
6932 | RStructList (n, typ) ->
6933 let cols = cols_of_struct typ in
6934 generate_perl_struct_list_code typ cols name style n do_cleanups
6937 pr " char *%s;\n" n;
6938 pr " size_t size;\n";
6940 pr " %s = guestfs_%s " n name;
6941 generate_c_call_args ~handle:"g" style;
6944 pr " if (%s == NULL)\n" n;
6945 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6946 pr " RETVAL = newSVpv (%s, size);\n" n;
6947 pr " free (%s);\n" n;
6955 and generate_perl_struct_list_code typ cols name style n do_cleanups =
6957 pr " struct guestfs_%s_list *%s;\n" typ n;
6961 pr " %s = guestfs_%s " n name;
6962 generate_c_call_args ~handle:"g" style;
6965 pr " if (%s == NULL)\n" n;
6966 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6967 pr " EXTEND (SP, %s->len);\n" n;
6968 pr " for (i = 0; i < %s->len; ++i) {\n" n;
6969 pr " hv = newHV ();\n";
6973 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
6974 name (String.length name) n name
6976 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
6977 name (String.length name) n name
6979 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
6980 name (String.length name) n name n name
6981 | name, (FBytes|FUInt64) ->
6982 pr " (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
6983 name (String.length name) n name
6985 pr " (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
6986 name (String.length name) n name
6987 | name, (FInt32|FUInt32) ->
6988 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
6989 name (String.length name) n name
6991 pr " (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
6992 name (String.length name) n name
6993 | name, FOptPercent ->
6994 pr " (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
6995 name (String.length name) n name
6997 pr " PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
6999 pr " guestfs_free_%s_list (%s);\n" typ n
7001 and generate_perl_struct_code typ cols name style n do_cleanups =
7003 pr " struct guestfs_%s *%s;\n" typ n;
7005 pr " %s = guestfs_%s " n name;
7006 generate_c_call_args ~handle:"g" style;
7009 pr " if (%s == NULL)\n" n;
7010 pr " croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7011 pr " EXTEND (SP, 2 * %d);\n" (List.length cols);
7013 fun ((name, _) as col) ->
7014 pr " PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7018 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7021 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7024 pr " PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7026 | name, (FBytes|FUInt64) ->
7027 pr " PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7030 pr " PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7032 | name, (FInt32|FUInt32) ->
7033 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7036 pr " PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7038 | name, FOptPercent ->
7039 pr " PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7042 pr " free (%s);\n" n
7044 (* Generate Sys/Guestfs.pm. *)
7045 and generate_perl_pm () =
7046 generate_header HashStyle LGPLv2;
7053 Sys::Guestfs - Perl bindings for libguestfs
7059 my $h = Sys::Guestfs->new ();
7060 $h->add_drive ('guest.img');
7063 $h->mount ('/dev/sda1', '/');
7064 $h->touch ('/hello');
7069 The C<Sys::Guestfs> module provides a Perl XS binding to the
7070 libguestfs API for examining and modifying virtual machine
7073 Amongst the things this is good for: making batch configuration
7074 changes to guests, getting disk used/free statistics (see also:
7075 virt-df), migrating between virtualization systems (see also:
7076 virt-p2v), performing partial backups, performing partial guest
7077 clones, cloning guests and changing registry/UUID/hostname info, and
7080 Libguestfs uses Linux kernel and qemu code, and can access any type of
7081 guest filesystem that Linux and qemu can, including but not limited
7082 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7083 schemes, qcow, qcow2, vmdk.
7085 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7086 LVs, what filesystem is in each LV, etc.). It can also run commands
7087 in the context of the guest. Also you can access filesystems over FTP.
7089 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7090 functions for using libguestfs from Perl, including integration
7095 All errors turn into calls to C<croak> (see L<Carp(3)>).
7103 package Sys::Guestfs;
7109 XSLoader::load ('Sys::Guestfs');
7111 =item $h = Sys::Guestfs->new ();
7113 Create a new guestfs handle.
7119 my $class = ref ($proto) || $proto;
7121 my $self = Sys::Guestfs::_create ();
7122 bless $self, $class;
7128 (* Actions. We only need to print documentation for these as
7129 * they are pulled in from the XS code automatically.
7132 fun (name, style, _, flags, _, _, longdesc) ->
7133 if not (List.mem NotInDocs flags) then (
7134 let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7136 generate_perl_prototype name style;
7138 pr "%s\n\n" longdesc;
7139 if List.mem ProtocolLimitWarning flags then
7140 pr "%s\n\n" protocol_limit_warning;
7141 if List.mem DangerWillRobinson flags then
7142 pr "%s\n\n" danger_will_robinson;
7143 match deprecation_notice flags with
7145 | Some txt -> pr "%s\n\n" txt
7147 ) all_functions_sorted;
7159 Copyright (C) 2009 Red Hat Inc.
7163 Please see the file COPYING.LIB for the full license.
7169 L<http://libguestfs.org>,
7170 L<Sys::Guestfs::Lib(3)>.
7175 and generate_perl_prototype name style =
7176 (match fst style with
7184 | RBufferOut n -> pr "$%s = " n
7186 | RHashtable n -> pr "%%%s = " n
7188 | RStructList (n,_) -> pr "@%s = " n
7191 let comma = ref false in
7194 if !comma then pr ", ";
7197 | String n | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7204 (* Generate Python C module. *)
7205 and generate_python_c () =
7206 generate_header CStyle LGPLv2;
7215 #include \"guestfs.h\"
7223 get_handle (PyObject *obj)
7226 assert (obj != Py_None);
7227 return ((Pyguestfs_Object *) obj)->g;
7231 put_handle (guestfs_h *g)
7235 PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7238 /* This list should be freed (but not the strings) after use. */
7239 static const char **
7240 get_string_list (PyObject *obj)
7247 if (!PyList_Check (obj)) {
7248 PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7252 len = PyList_Size (obj);
7253 r = malloc (sizeof (char *) * (len+1));
7255 PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7259 for (i = 0; i < len; ++i)
7260 r[i] = PyString_AsString (PyList_GetItem (obj, i));
7267 put_string_list (char * const * const argv)
7272 for (argc = 0; argv[argc] != NULL; ++argc)
7275 list = PyList_New (argc);
7276 for (i = 0; i < argc; ++i)
7277 PyList_SetItem (list, i, PyString_FromString (argv[i]));
7283 put_table (char * const * const argv)
7285 PyObject *list, *item;
7288 for (argc = 0; argv[argc] != NULL; ++argc)
7291 list = PyList_New (argc >> 1);
7292 for (i = 0; i < argc; i += 2) {
7293 item = PyTuple_New (2);
7294 PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7295 PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7296 PyList_SetItem (list, i >> 1, item);
7303 free_strings (char **argv)
7307 for (argc = 0; argv[argc] != NULL; ++argc)
7313 py_guestfs_create (PyObject *self, PyObject *args)
7317 g = guestfs_create ();
7319 PyErr_SetString (PyExc_RuntimeError,
7320 \"guestfs.create: failed to allocate handle\");
7323 guestfs_set_error_handler (g, NULL, NULL);
7324 return put_handle (g);
7328 py_guestfs_close (PyObject *self, PyObject *args)
7333 if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7335 g = get_handle (py_g);
7339 Py_INCREF (Py_None);
7345 (* Structures, turned into Python dictionaries. *)
7348 pr "static PyObject *\n";
7349 pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7351 pr " PyObject *dict;\n";
7353 pr " dict = PyDict_New ();\n";
7357 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7358 pr " PyString_FromString (%s->%s));\n"
7361 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7362 pr " PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7365 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7366 pr " PyString_FromStringAndSize (%s->%s, 32));\n"
7368 | name, (FBytes|FUInt64) ->
7369 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7370 pr " PyLong_FromUnsignedLongLong (%s->%s));\n"
7373 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7374 pr " PyLong_FromLongLong (%s->%s));\n"
7377 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7378 pr " PyLong_FromUnsignedLong (%s->%s));\n"
7381 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7382 pr " PyLong_FromLong (%s->%s));\n"
7384 | name, FOptPercent ->
7385 pr " if (%s->%s >= 0)\n" typ name;
7386 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7387 pr " PyFloat_FromDouble ((double) %s->%s));\n"
7390 pr " Py_INCREF (Py_None);\n";
7391 pr " PyDict_SetItemString (dict, \"%s\", Py_None);" name;
7394 pr " PyDict_SetItemString (dict, \"%s\",\n" name;
7395 pr " PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7397 pr " return dict;\n";
7401 pr "static PyObject *\n";
7402 pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7404 pr " PyObject *list;\n";
7407 pr " list = PyList_New (%ss->len);\n" typ;
7408 pr " for (i = 0; i < %ss->len; ++i)\n" typ;
7409 pr " PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7410 pr " return list;\n";
7415 (* Python wrapper functions. *)
7417 fun (name, style, _, _, _, _, _) ->
7418 pr "static PyObject *\n";
7419 pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7422 pr " PyObject *py_g;\n";
7423 pr " guestfs_h *g;\n";
7424 pr " PyObject *py_r;\n";
7427 match fst style with
7428 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7429 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7430 | RConstString _ | RConstOptString _ ->
7431 pr " const char *r;\n"; "NULL"
7432 | RString _ -> pr " char *r;\n"; "NULL"
7433 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7434 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7435 | RStructList (_, typ) ->
7436 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7439 pr " size_t size;\n";
7444 | String n | FileIn n | FileOut n -> pr " const char *%s;\n" n
7445 | OptString n -> pr " const char *%s;\n" n
7447 pr " PyObject *py_%s;\n" n;
7448 pr " const char **%s;\n" n
7449 | Bool n -> pr " int %s;\n" n
7450 | Int n -> pr " int %s;\n" n
7455 (* Convert the parameters. *)
7456 pr " if (!PyArg_ParseTuple (args, (char *) \"O";
7459 | String _ | FileIn _ | FileOut _ -> pr "s"
7460 | OptString _ -> pr "z"
7461 | StringList _ -> pr "O"
7462 | Bool _ -> pr "i" (* XXX Python has booleans? *)
7465 pr ":guestfs_%s\",\n" name;
7469 | String n | FileIn n | FileOut n -> pr ", &%s" n
7470 | OptString n -> pr ", &%s" n
7471 | StringList n -> pr ", &py_%s" n
7472 | Bool n -> pr ", &%s" n
7473 | Int n -> pr ", &%s" n
7477 pr " return NULL;\n";
7479 pr " g = get_handle (py_g);\n";
7482 | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7484 pr " %s = get_string_list (py_%s);\n" n n;
7485 pr " if (!%s) return NULL;\n" n
7490 pr " r = guestfs_%s " name;
7491 generate_c_call_args ~handle:"g" style;
7496 | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7498 pr " free (%s);\n" n
7501 pr " if (r == %s) {\n" error_code;
7502 pr " PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7503 pr " return NULL;\n";
7507 (match fst style with
7509 pr " Py_INCREF (Py_None);\n";
7510 pr " py_r = Py_None;\n"
7512 | RBool _ -> pr " py_r = PyInt_FromLong ((long) r);\n"
7513 | RInt64 _ -> pr " py_r = PyLong_FromLongLong (r);\n"
7514 | RConstString _ -> pr " py_r = PyString_FromString (r);\n"
7515 | RConstOptString _ ->
7517 pr " py_r = PyString_FromString (r);\n";
7519 pr " Py_INCREF (Py_None);\n";
7520 pr " py_r = Py_None;\n";
7523 pr " py_r = PyString_FromString (r);\n";
7526 pr " py_r = put_string_list (r);\n";
7527 pr " free_strings (r);\n"
7528 | RStruct (_, typ) ->
7529 pr " py_r = put_%s (r);\n" typ;
7530 pr " guestfs_free_%s (r);\n" typ
7531 | RStructList (_, typ) ->
7532 pr " py_r = put_%s_list (r);\n" typ;
7533 pr " guestfs_free_%s_list (r);\n" typ
7535 pr " py_r = put_table (r);\n";
7536 pr " free_strings (r);\n"
7538 pr " py_r = PyString_FromStringAndSize (r, size);\n";
7542 pr " return py_r;\n";
7547 (* Table of functions. *)
7548 pr "static PyMethodDef methods[] = {\n";
7549 pr " { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7550 pr " { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7552 fun (name, _, _, _, _, _, _) ->
7553 pr " { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7556 pr " { NULL, NULL, 0, NULL }\n";
7560 (* Init function. *)
7563 initlibguestfsmod (void)
7565 static int initialized = 0;
7567 if (initialized) return;
7568 Py_InitModule ((char *) \"libguestfsmod\", methods);
7573 (* Generate Python module. *)
7574 and generate_python_py () =
7575 generate_header HashStyle LGPLv2;
7578 u\"\"\"Python bindings for libguestfs
7581 g = guestfs.GuestFS ()
7582 g.add_drive (\"guest.img\")
7585 parts = g.list_partitions ()
7587 The guestfs module provides a Python binding to the libguestfs API
7588 for examining and modifying virtual machine disk images.
7590 Amongst the things this is good for: making batch configuration
7591 changes to guests, getting disk used/free statistics (see also:
7592 virt-df), migrating between virtualization systems (see also:
7593 virt-p2v), performing partial backups, performing partial guest
7594 clones, cloning guests and changing registry/UUID/hostname info, and
7597 Libguestfs uses Linux kernel and qemu code, and can access any type of
7598 guest filesystem that Linux and qemu can, including but not limited
7599 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7600 schemes, qcow, qcow2, vmdk.
7602 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7603 LVs, what filesystem is in each LV, etc.). It can also run commands
7604 in the context of the guest. Also you can access filesystems over FTP.
7606 Errors which happen while using the API are turned into Python
7607 RuntimeError exceptions.
7609 To create a guestfs handle you usually have to perform the following
7612 # Create the handle, call add_drive at least once, and possibly
7613 # several times if the guest has multiple block devices:
7614 g = guestfs.GuestFS ()
7615 g.add_drive (\"guest.img\")
7617 # Launch the qemu subprocess and wait for it to become ready:
7621 # Now you can issue commands, for example:
7626 import libguestfsmod
7629 \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7631 def __init__ (self):
7632 \"\"\"Create a new libguestfs handle.\"\"\"
7633 self._o = libguestfsmod.create ()
7636 libguestfsmod.close (self._o)
7641 fun (name, style, _, flags, _, _, longdesc) ->
7643 generate_py_call_args ~handle:"self" (snd style);
7646 if not (List.mem NotInDocs flags) then (
7647 let doc = replace_str longdesc "C<guestfs_" "C<g." in
7649 match fst style with
7650 | RErr | RInt _ | RInt64 _ | RBool _
7651 | RConstOptString _ | RConstString _
7652 | RString _ | RBufferOut _ -> doc
7654 doc ^ "\n\nThis function returns a list of strings."
7655 | RStruct (_, typ) ->
7656 doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7657 | RStructList (_, typ) ->
7658 doc ^ sprintf "\n\nThis function returns a list of %ss. Each %s is represented as a dictionary." typ typ
7660 doc ^ "\n\nThis function returns a dictionary." in
7662 if List.mem ProtocolLimitWarning flags then
7663 doc ^ "\n\n" ^ protocol_limit_warning
7666 if List.mem DangerWillRobinson flags then
7667 doc ^ "\n\n" ^ danger_will_robinson
7670 match deprecation_notice flags with
7672 | Some txt -> doc ^ "\n\n" ^ txt in
7673 let doc = pod2text ~width:60 name doc in
7674 let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
7675 let doc = String.concat "\n " doc in
7676 pr " u\"\"\"%s\"\"\"\n" doc;
7678 pr " return libguestfsmod.%s " name;
7679 generate_py_call_args ~handle:"self._o" (snd style);
7684 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
7685 and generate_py_call_args ~handle args =
7687 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
7690 (* Useful if you need the longdesc POD text as plain text. Returns a
7693 * Because this is very slow (the slowest part of autogeneration),
7694 * we memoize the results.
7696 and pod2text ~width name longdesc =
7697 let key = width, name, longdesc in
7698 try Hashtbl.find pod2text_memo key
7700 let filename, chan = Filename.open_temp_file "gen" ".tmp" in
7701 fprintf chan "=head1 %s\n\n%s\n" name longdesc;
7703 let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
7704 let chan = Unix.open_process_in cmd in
7705 let lines = ref [] in
7707 let line = input_line chan in
7708 if i = 1 then (* discard the first line of output *)
7711 let line = triml line in
7712 lines := line :: !lines;
7715 let lines = try loop 1 with End_of_file -> List.rev !lines in
7716 Unix.unlink filename;
7717 (match Unix.close_process_in chan with
7718 | Unix.WEXITED 0 -> ()
7720 failwithf "pod2text: process exited with non-zero status (%d)" i
7721 | Unix.WSIGNALED i | Unix.WSTOPPED i ->
7722 failwithf "pod2text: process signalled or stopped by signal %d" i
7724 Hashtbl.add pod2text_memo key lines;
7725 let chan = open_out pod2text_memo_filename in
7726 output_value chan pod2text_memo;
7730 (* Generate ruby bindings. *)
7731 and generate_ruby_c () =
7732 generate_header CStyle LGPLv2;
7740 #include \"guestfs.h\"
7742 #include \"extconf.h\"
7744 /* For Ruby < 1.9 */
7746 #define RARRAY_LEN(r) (RARRAY((r))->len)
7749 static VALUE m_guestfs; /* guestfs module */
7750 static VALUE c_guestfs; /* guestfs_h handle */
7751 static VALUE e_Error; /* used for all errors */
7753 static void ruby_guestfs_free (void *p)
7756 guestfs_close ((guestfs_h *) p);
7759 static VALUE ruby_guestfs_create (VALUE m)
7763 g = guestfs_create ();
7765 rb_raise (e_Error, \"failed to create guestfs handle\");
7767 /* Don't print error messages to stderr by default. */
7768 guestfs_set_error_handler (g, NULL, NULL);
7770 /* Wrap it, and make sure the close function is called when the
7773 return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
7776 static VALUE ruby_guestfs_close (VALUE gv)
7779 Data_Get_Struct (gv, guestfs_h, g);
7781 ruby_guestfs_free (g);
7782 DATA_PTR (gv) = NULL;
7790 fun (name, style, _, _, _, _, _) ->
7791 pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
7792 List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
7795 pr " guestfs_h *g;\n";
7796 pr " Data_Get_Struct (gv, guestfs_h, g);\n";
7798 pr " rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
7804 | String n | FileIn n | FileOut n ->
7805 pr " Check_Type (%sv, T_STRING);\n" n;
7806 pr " const char *%s = StringValueCStr (%sv);\n" n n;
7808 pr " rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
7809 pr " \"%s\", \"%s\");\n" n name
7811 pr " const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
7813 pr " char **%s;\n" n;
7814 pr " Check_Type (%sv, T_ARRAY);\n" n;
7816 pr " int i, len;\n";
7817 pr " len = RARRAY_LEN (%sv);\n" n;
7818 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
7820 pr " for (i = 0; i < len; ++i) {\n";
7821 pr " VALUE v = rb_ary_entry (%sv, i);\n" n;
7822 pr " %s[i] = StringValueCStr (v);\n" n;
7824 pr " %s[len] = NULL;\n" n;
7827 pr " int %s = RTEST (%sv);\n" n n
7829 pr " int %s = NUM2INT (%sv);\n" n n
7834 match fst style with
7835 | RErr | RInt _ | RBool _ -> pr " int r;\n"; "-1"
7836 | RInt64 _ -> pr " int64_t r;\n"; "-1"
7837 | RConstString _ | RConstOptString _ ->
7838 pr " const char *r;\n"; "NULL"
7839 | RString _ -> pr " char *r;\n"; "NULL"
7840 | RStringList _ | RHashtable _ -> pr " char **r;\n"; "NULL"
7841 | RStruct (_, typ) -> pr " struct guestfs_%s *r;\n" typ; "NULL"
7842 | RStructList (_, typ) ->
7843 pr " struct guestfs_%s_list *r;\n" typ; "NULL"
7846 pr " size_t size;\n";
7850 pr " r = guestfs_%s " name;
7851 generate_c_call_args ~handle:"g" style;
7856 | String _ | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7858 pr " free (%s);\n" n
7861 pr " if (r == %s)\n" error_code;
7862 pr " rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
7865 (match fst style with
7867 pr " return Qnil;\n"
7868 | RInt _ | RBool _ ->
7869 pr " return INT2NUM (r);\n"
7871 pr " return ULL2NUM (r);\n"
7873 pr " return rb_str_new2 (r);\n";
7874 | RConstOptString _ ->
7876 pr " return rb_str_new2 (r);\n";
7878 pr " return Qnil;\n";
7880 pr " VALUE rv = rb_str_new2 (r);\n";
7884 pr " int i, len = 0;\n";
7885 pr " for (i = 0; r[i] != NULL; ++i) len++;\n";
7886 pr " VALUE rv = rb_ary_new2 (len);\n";
7887 pr " for (i = 0; r[i] != NULL; ++i) {\n";
7888 pr " rb_ary_push (rv, rb_str_new2 (r[i]));\n";
7889 pr " free (r[i]);\n";
7893 | RStruct (_, typ) ->
7894 let cols = cols_of_struct typ in
7895 generate_ruby_struct_code typ cols
7896 | RStructList (_, typ) ->
7897 let cols = cols_of_struct typ in
7898 generate_ruby_struct_list_code typ cols
7900 pr " VALUE rv = rb_hash_new ();\n";
7902 pr " for (i = 0; r[i] != NULL; i+=2) {\n";
7903 pr " rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
7904 pr " free (r[i]);\n";
7905 pr " free (r[i+1]);\n";
7910 pr " VALUE rv = rb_str_new (r, size);\n";
7920 /* Initialize the module. */
7921 void Init__guestfs ()
7923 m_guestfs = rb_define_module (\"Guestfs\");
7924 c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
7925 e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
7927 rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
7928 rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
7931 (* Define the rest of the methods. *)
7933 fun (name, style, _, _, _, _, _) ->
7934 pr " rb_define_method (c_guestfs, \"%s\",\n" name;
7935 pr " ruby_guestfs_%s, %d);\n" name (List.length (snd style))
7940 (* Ruby code to return a struct. *)
7941 and generate_ruby_struct_code typ cols =
7942 pr " VALUE rv = rb_hash_new ();\n";
7946 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
7948 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
7950 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
7951 | name, (FBytes|FUInt64) ->
7952 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
7954 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
7956 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
7958 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
7959 | name, FOptPercent ->
7960 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
7961 | name, FChar -> (* XXX wrong? *)
7962 pr " rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
7964 pr " guestfs_free_%s (r);\n" typ;
7967 (* Ruby code to return a struct list. *)
7968 and generate_ruby_struct_list_code typ cols =
7969 pr " VALUE rv = rb_ary_new2 (r->len);\n";
7971 pr " for (i = 0; i < r->len; ++i) {\n";
7972 pr " VALUE hv = rb_hash_new ();\n";
7976 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
7978 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
7980 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
7981 | name, (FBytes|FUInt64) ->
7982 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
7984 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
7986 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
7988 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
7989 | name, FOptPercent ->
7990 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
7991 | name, FChar -> (* XXX wrong? *)
7992 pr " rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
7994 pr " rb_ary_push (rv, hv);\n";
7996 pr " guestfs_free_%s_list (r);\n" typ;
7999 (* Generate Java bindings GuestFS.java file. *)
8000 and generate_java_java () =
8001 generate_header CStyle LGPLv2;
8004 package com.redhat.et.libguestfs;
8006 import java.util.HashMap;
8007 import com.redhat.et.libguestfs.LibGuestFSException;
8008 import com.redhat.et.libguestfs.PV;
8009 import com.redhat.et.libguestfs.VG;
8010 import com.redhat.et.libguestfs.LV;
8011 import com.redhat.et.libguestfs.Stat;
8012 import com.redhat.et.libguestfs.StatVFS;
8013 import com.redhat.et.libguestfs.IntBool;
8014 import com.redhat.et.libguestfs.Dirent;
8017 * The GuestFS object is a libguestfs handle.
8021 public class GuestFS {
8022 // Load the native code.
8024 System.loadLibrary (\"guestfs_jni\");
8028 * The native guestfs_h pointer.
8033 * Create a libguestfs handle.
8035 * @throws LibGuestFSException
8037 public GuestFS () throws LibGuestFSException
8041 private native long _create () throws LibGuestFSException;
8044 * Close a libguestfs handle.
8046 * You can also leave handles to be collected by the garbage
8047 * collector, but this method ensures that the resources used
8048 * by the handle are freed up immediately. If you call any
8049 * other methods after closing the handle, you will get an
8052 * @throws LibGuestFSException
8054 public void close () throws LibGuestFSException
8060 private native void _close (long g) throws LibGuestFSException;
8062 public void finalize () throws LibGuestFSException
8070 fun (name, style, _, flags, _, shortdesc, longdesc) ->
8071 if not (List.mem NotInDocs flags); then (
8072 let doc = replace_str longdesc "C<guestfs_" "C<g." in
8074 if List.mem ProtocolLimitWarning flags then
8075 doc ^ "\n\n" ^ protocol_limit_warning
8078 if List.mem DangerWillRobinson flags then
8079 doc ^ "\n\n" ^ danger_will_robinson
8082 match deprecation_notice flags with
8084 | Some txt -> doc ^ "\n\n" ^ txt in
8085 let doc = pod2text ~width:60 name doc in
8086 let doc = List.map ( (* RHBZ#501883 *)
8089 | nonempty -> nonempty
8091 let doc = String.concat "\n * " doc in
8094 pr " * %s\n" shortdesc;
8097 pr " * @throws LibGuestFSException\n";
8101 generate_java_prototype ~public:true ~semicolon:false name style;
8104 pr " if (g == 0)\n";
8105 pr " throw new LibGuestFSException (\"%s: handle is closed\");\n"
8108 if fst style <> RErr then pr "return ";
8110 generate_java_call_args ~handle:"g" (snd style);
8114 generate_java_prototype ~privat:true ~native:true name style;
8121 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8122 and generate_java_call_args ~handle args =
8124 List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8127 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8128 ?(semicolon=true) name style =
8129 if privat then pr "private ";
8130 if public then pr "public ";
8131 if native then pr "native ";
8134 (match fst style with
8135 | RErr -> pr "void ";
8136 | RInt _ -> pr "int ";
8137 | RInt64 _ -> pr "long ";
8138 | RBool _ -> pr "boolean ";
8139 | RConstString _ | RConstOptString _ | RString _
8140 | RBufferOut _ -> pr "String ";
8141 | RStringList _ -> pr "String[] ";
8142 | RStruct (_, typ) ->
8143 let name = java_name_of_struct typ in
8145 | RStructList (_, typ) ->
8146 let name = java_name_of_struct typ in
8148 | RHashtable _ -> pr "HashMap<String,String> ";
8151 if native then pr "_%s " name else pr "%s " name;
8153 let needs_comma = ref false in
8162 if !needs_comma then pr ", ";
8163 needs_comma := true;
8180 pr " throws LibGuestFSException";
8181 if semicolon then pr ";"
8183 and generate_java_struct jtyp cols =
8184 generate_header CStyle LGPLv2;
8187 package com.redhat.et.libguestfs;
8190 * Libguestfs %s structure.
8202 | name, FBuffer -> pr " public String %s;\n" name
8203 | name, (FBytes|FUInt64|FInt64) -> pr " public long %s;\n" name
8204 | name, (FUInt32|FInt32) -> pr " public int %s;\n" name
8205 | name, FChar -> pr " public char %s;\n" name
8206 | name, FOptPercent ->
8207 pr " /* The next field is [0..100] or -1 meaning 'not present': */\n";
8208 pr " public float %s;\n" name
8213 and generate_java_c () =
8214 generate_header CStyle LGPLv2;
8221 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8222 #include \"guestfs.h\"
8224 /* Note that this function returns. The exception is not thrown
8225 * until after the wrapper function returns.
8228 throw_exception (JNIEnv *env, const char *msg)
8231 cl = (*env)->FindClass (env,
8232 \"com/redhat/et/libguestfs/LibGuestFSException\");
8233 (*env)->ThrowNew (env, cl, msg);
8236 JNIEXPORT jlong JNICALL
8237 Java_com_redhat_et_libguestfs_GuestFS__1create
8238 (JNIEnv *env, jobject obj)
8242 g = guestfs_create ();
8244 throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8247 guestfs_set_error_handler (g, NULL, NULL);
8248 return (jlong) (long) g;
8251 JNIEXPORT void JNICALL
8252 Java_com_redhat_et_libguestfs_GuestFS__1close
8253 (JNIEnv *env, jobject obj, jlong jg)
8255 guestfs_h *g = (guestfs_h *) (long) jg;
8262 fun (name, style, _, _, _, _, _) ->
8264 (match fst style with
8265 | RErr -> pr "void ";
8266 | RInt _ -> pr "jint ";
8267 | RInt64 _ -> pr "jlong ";
8268 | RBool _ -> pr "jboolean ";
8269 | RConstString _ | RConstOptString _ | RString _
8270 | RBufferOut _ -> pr "jstring ";
8271 | RStruct _ | RHashtable _ ->
8273 | RStringList _ | RStructList _ ->
8277 pr "Java_com_redhat_et_libguestfs_GuestFS_";
8278 pr "%s" (replace_str ("_" ^ name) "_" "_1");
8280 pr " (JNIEnv *env, jobject obj, jlong jg";
8287 pr ", jstring j%s" n
8289 pr ", jobjectArray j%s" n
8291 pr ", jboolean j%s" n
8297 pr " guestfs_h *g = (guestfs_h *) (long) jg;\n";
8298 let error_code, no_ret =
8299 match fst style with
8300 | RErr -> pr " int r;\n"; "-1", ""
8302 | RInt _ -> pr " int r;\n"; "-1", "0"
8303 | RInt64 _ -> pr " int64_t r;\n"; "-1", "0"
8304 | RConstString _ -> pr " const char *r;\n"; "NULL", "NULL"
8305 | RConstOptString _ -> pr " const char *r;\n"; "NULL", "NULL"
8307 pr " jstring jr;\n";
8308 pr " char *r;\n"; "NULL", "NULL"
8310 pr " jobjectArray jr;\n";
8313 pr " jstring jstr;\n";
8314 pr " char **r;\n"; "NULL", "NULL"
8315 | RStruct (_, typ) ->
8316 pr " jobject jr;\n";
8318 pr " jfieldID fl;\n";
8319 pr " struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8320 | RStructList (_, typ) ->
8321 pr " jobjectArray jr;\n";
8323 pr " jfieldID fl;\n";
8324 pr " jobject jfl;\n";
8325 pr " struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8326 | RHashtable _ -> pr " char **r;\n"; "NULL", "NULL"
8328 pr " jstring jr;\n";
8330 pr " size_t size;\n";
8338 pr " const char *%s;\n" n
8340 pr " int %s_len;\n" n;
8341 pr " const char **%s;\n" n
8348 (match fst style with
8349 | RStringList _ | RStructList _ -> true
8350 | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8352 | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8353 List.exists (function StringList _ -> true | _ -> false) (snd style) in
8359 (* Get the parameters. *)
8365 pr " %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8367 (* This is completely undocumented, but Java null becomes
8370 pr " %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8372 pr " %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8373 pr " %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8374 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8375 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8377 pr " %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8379 pr " %s[%s_len] = NULL;\n" n n;
8382 pr " %s = j%s;\n" n n
8385 (* Make the call. *)
8386 pr " r = guestfs_%s " name;
8387 generate_c_call_args ~handle:"g" style;
8390 (* Release the parameters. *)
8396 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8399 pr " (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8401 pr " for (i = 0; i < %s_len; ++i) {\n" n;
8402 pr " jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8404 pr " (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8406 pr " free (%s);\n" n
8411 (* Check for errors. *)
8412 pr " if (r == %s) {\n" error_code;
8413 pr " throw_exception (env, guestfs_last_error (g));\n";
8414 pr " return %s;\n" no_ret;
8418 (match fst style with
8420 | RInt _ -> pr " return (jint) r;\n"
8421 | RBool _ -> pr " return (jboolean) r;\n"
8422 | RInt64 _ -> pr " return (jlong) r;\n"
8423 | RConstString _ -> pr " return (*env)->NewStringUTF (env, r);\n"
8424 | RConstOptString _ ->
8425 pr " return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8427 pr " jr = (*env)->NewStringUTF (env, r);\n";
8431 pr " for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8432 pr " cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8433 pr " jstr = (*env)->NewStringUTF (env, \"\");\n";
8434 pr " jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8435 pr " for (i = 0; i < r_len; ++i) {\n";
8436 pr " jstr = (*env)->NewStringUTF (env, r[i]);\n";
8437 pr " (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8438 pr " free (r[i]);\n";
8442 | RStruct (_, typ) ->
8443 let jtyp = java_name_of_struct typ in
8444 let cols = cols_of_struct typ in
8445 generate_java_struct_return typ jtyp cols
8446 | RStructList (_, typ) ->
8447 let jtyp = java_name_of_struct typ in
8448 let cols = cols_of_struct typ in
8449 generate_java_struct_list_return typ jtyp cols
8452 pr " throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8453 pr " return NULL;\n"
8455 pr " jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8464 and generate_java_struct_return typ jtyp cols =
8465 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8466 pr " jr = (*env)->AllocObject (env, cl);\n";
8470 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8471 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8474 pr " char s[33];\n";
8475 pr " memcpy (s, r->%s, 32);\n" name;
8477 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8478 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8482 pr " int len = r->%s_len;\n" name;
8483 pr " char s[len+1];\n";
8484 pr " memcpy (s, r->%s, len);\n" name;
8485 pr " s[len] = 0;\n";
8486 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8487 pr " (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8489 | name, (FBytes|FUInt64|FInt64) ->
8490 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8491 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8492 | name, (FUInt32|FInt32) ->
8493 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8494 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8495 | name, FOptPercent ->
8496 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8497 pr " (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8499 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8500 pr " (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8505 and generate_java_struct_list_return typ jtyp cols =
8506 pr " cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8507 pr " jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8508 pr " for (i = 0; i < r->len; ++i) {\n";
8509 pr " jfl = (*env)->AllocObject (env, cl);\n";
8513 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8514 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8517 pr " char s[33];\n";
8518 pr " memcpy (s, r->val[i].%s, 32);\n" name;
8520 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8521 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8525 pr " int len = r->val[i].%s_len;\n" name;
8526 pr " char s[len+1];\n";
8527 pr " memcpy (s, r->val[i].%s, len);\n" name;
8528 pr " s[len] = 0;\n";
8529 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8530 pr " (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8532 | name, (FBytes|FUInt64|FInt64) ->
8533 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8534 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8535 | name, (FUInt32|FInt32) ->
8536 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8537 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8538 | name, FOptPercent ->
8539 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8540 pr " (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8542 pr " fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8543 pr " (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8545 pr " (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8547 pr " guestfs_free_%s_list (r);\n" typ;
8550 and generate_java_makefile_inc () =
8551 generate_header HashStyle GPLv2;
8553 pr "java_built_sources = \\\n";
8556 pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8558 pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8560 and generate_haskell_hs () =
8561 generate_header HaskellStyle LGPLv2;
8563 (* XXX We only know how to generate partial FFI for Haskell
8564 * at the moment. Please help out!
8566 let can_generate style =
8570 | RInt64 _, _ -> true
8573 | RConstOptString _, _
8579 | RBufferOut _, _ -> false in
8582 {-# INCLUDE <guestfs.h> #-}
8583 {-# LANGUAGE ForeignFunctionInterface #-}
8588 (* List out the names of the actions we want to export. *)
8590 fun (name, style, _, _, _, _, _) ->
8591 if can_generate style then pr ",\n %s" name
8598 import Foreign.C.Types
8600 import Control.Exception
8601 import Data.Typeable
8603 data GuestfsS = GuestfsS -- represents the opaque C struct
8604 type GuestfsP = Ptr GuestfsS -- guestfs_h *
8605 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8607 -- XXX define properly later XXX
8611 data IntBool = IntBool
8613 data StatVFS = StatVFS
8614 data Hashtable = Hashtable
8616 foreign import ccall unsafe \"guestfs_create\" c_create
8618 foreign import ccall unsafe \"&guestfs_close\" c_close
8619 :: FunPtr (GuestfsP -> IO ())
8620 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8621 :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8623 create :: IO GuestfsH
8626 c_set_error_handler p nullPtr nullPtr
8627 h <- newForeignPtr c_close p
8630 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8631 :: GuestfsP -> IO CString
8633 -- last_error :: GuestfsH -> IO (Maybe String)
8634 -- last_error h = do
8635 -- str <- withForeignPtr h (\\p -> c_last_error p)
8636 -- maybePeek peekCString str
8638 last_error :: GuestfsH -> IO (String)
8640 str <- withForeignPtr h (\\p -> c_last_error p)
8642 then return \"no error\"
8643 else peekCString str
8647 (* Generate wrappers for each foreign function. *)
8649 fun (name, style, _, _, _, _, _) ->
8650 if can_generate style then (
8651 pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8653 generate_haskell_prototype ~handle:"GuestfsP" style;
8657 generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
8659 pr "%s %s = do\n" name
8660 (String.concat " " ("h" :: List.map name_of_argt (snd style)));
8662 (* Convert pointer arguments using with* functions. *)
8667 | String n -> pr "withCString %s $ \\%s -> " n n
8668 | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
8669 | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
8670 | Bool _ | Int _ -> ()
8672 (* Convert integer arguments. *)
8676 | Bool n -> sprintf "(fromBool %s)" n
8677 | Int n -> sprintf "(fromIntegral %s)" n
8678 | FileIn n | FileOut n | String n | OptString n | StringList n -> n
8680 pr "withForeignPtr h (\\p -> c_%s %s)\n" name
8681 (String.concat " " ("p" :: args));
8682 (match fst style with
8683 | RErr | RInt _ | RInt64 _ | RBool _ ->
8684 pr " if (r == -1)\n";
8686 pr " err <- last_error h\n";
8688 | RConstString _ | RConstOptString _ | RString _
8689 | RStringList _ | RStruct _
8690 | RStructList _ | RHashtable _ | RBufferOut _ ->
8691 pr " if (r == nullPtr)\n";
8693 pr " err <- last_error h\n";
8696 (match fst style with
8698 pr " else return ()\n"
8700 pr " else return (fromIntegral r)\n"
8702 pr " else return (fromIntegral r)\n"
8704 pr " else return (toBool r)\n"
8713 pr " else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
8719 and generate_haskell_prototype ~handle ?(hs = false) style =
8721 let string = if hs then "String" else "CString" in
8722 let int = if hs then "Int" else "CInt" in
8723 let bool = if hs then "Bool" else "CInt" in
8724 let int64 = if hs then "Integer" else "Int64" in
8728 | String _ -> pr "%s" string
8729 | OptString _ -> if hs then pr "Maybe String" else pr "CString"
8730 | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
8731 | Bool _ -> pr "%s" bool
8732 | Int _ -> pr "%s" int
8733 | FileIn _ -> pr "%s" string
8734 | FileOut _ -> pr "%s" string
8739 (match fst style with
8740 | RErr -> if not hs then pr "CInt"
8741 | RInt _ -> pr "%s" int
8742 | RInt64 _ -> pr "%s" int64
8743 | RBool _ -> pr "%s" bool
8744 | RConstString _ -> pr "%s" string
8745 | RConstOptString _ -> pr "Maybe %s" string
8746 | RString _ -> pr "%s" string
8747 | RStringList _ -> pr "[%s]" string
8748 | RStruct (_, typ) ->
8749 let name = java_name_of_struct typ in
8751 | RStructList (_, typ) ->
8752 let name = java_name_of_struct typ in
8754 | RHashtable _ -> pr "Hashtable"
8755 | RBufferOut _ -> pr "%s" string
8759 and generate_bindtests () =
8760 generate_header CStyle LGPLv2;
8765 #include <inttypes.h>
8768 #include \"guestfs.h\"
8769 #include \"guestfs_protocol.h\"
8771 #define error guestfs_error
8772 #define safe_calloc guestfs_safe_calloc
8773 #define safe_malloc guestfs_safe_malloc
8776 print_strings (char * const* const argv)
8781 for (argc = 0; argv[argc] != NULL; ++argc) {
8782 if (argc > 0) printf (\", \");
8783 printf (\"\\\"%%s\\\"\", argv[argc]);
8788 /* The test0 function prints its parameters to stdout. */
8792 match test_functions with
8793 | [] -> assert false
8794 | test0 :: tests -> test0, tests in
8797 let (name, style, _, _, _, _, _) = test0 in
8798 generate_prototype ~extern:false ~semicolon:false ~newline:true
8799 ~handle:"g" ~prefix:"guestfs_" name style;
8805 | FileOut n -> pr " printf (\"%%s\\n\", %s);\n" n
8806 | OptString n -> pr " printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
8807 | StringList n -> pr " print_strings (%s);\n" n
8808 | Bool n -> pr " printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
8809 | Int n -> pr " printf (\"%%d\\n\", %s);\n" n
8811 pr " /* Java changes stdout line buffering so we need this: */\n";
8812 pr " fflush (stdout);\n";
8818 fun (name, style, _, _, _, _, _) ->
8819 if String.sub name (String.length name - 3) 3 <> "err" then (
8820 pr "/* Test normal return. */\n";
8821 generate_prototype ~extern:false ~semicolon:false ~newline:true
8822 ~handle:"g" ~prefix:"guestfs_" name style;
8824 (match fst style with
8829 pr " sscanf (val, \"%%d\", &r);\n";
8833 pr " sscanf (val, \"%%\" SCNi64, &r);\n";
8836 pr " return strcmp (val, \"true\") == 0;\n"
8838 | RConstOptString _ ->
8839 (* Can't return the input string here. Return a static
8840 * string so we ensure we get a segfault if the caller
8843 pr " return \"static string\";\n"
8845 pr " return strdup (val);\n"
8847 pr " char **strs;\n";
8849 pr " sscanf (val, \"%%d\", &n);\n";
8850 pr " strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
8851 pr " for (i = 0; i < n; ++i) {\n";
8852 pr " strs[i] = safe_malloc (g, 16);\n";
8853 pr " snprintf (strs[i], 16, \"%%d\", i);\n";
8855 pr " strs[n] = NULL;\n";
8856 pr " return strs;\n"
8857 | RStruct (_, typ) ->
8858 pr " struct guestfs_%s *r;\n" typ;
8859 pr " r = safe_calloc (g, sizeof *r, 1);\n";
8861 | RStructList (_, typ) ->
8862 pr " struct guestfs_%s_list *r;\n" typ;
8863 pr " r = safe_calloc (g, sizeof *r, 1);\n";
8864 pr " sscanf (val, \"%%d\", &r->len);\n";
8865 pr " r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
8868 pr " char **strs;\n";
8870 pr " sscanf (val, \"%%d\", &n);\n";
8871 pr " strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
8872 pr " for (i = 0; i < n; ++i) {\n";
8873 pr " strs[i*2] = safe_malloc (g, 16);\n";
8874 pr " strs[i*2+1] = safe_malloc (g, 16);\n";
8875 pr " snprintf (strs[i*2], 16, \"%%d\", i);\n";
8876 pr " snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
8878 pr " strs[n*2] = NULL;\n";
8879 pr " return strs;\n"
8881 pr " return strdup (val);\n"
8886 pr "/* Test error return. */\n";
8887 generate_prototype ~extern:false ~semicolon:false ~newline:true
8888 ~handle:"g" ~prefix:"guestfs_" name style;
8890 pr " error (g, \"error\");\n";
8891 (match fst style with
8892 | RErr | RInt _ | RInt64 _ | RBool _ ->
8894 | RConstString _ | RConstOptString _
8895 | RString _ | RStringList _ | RStruct _
8899 pr " return NULL;\n"
8906 and generate_ocaml_bindtests () =
8907 generate_header OCamlStyle GPLv2;
8911 let g = Guestfs.create () in
8918 | CallString s -> "\"" ^ s ^ "\""
8919 | CallOptString None -> "None"
8920 | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
8921 | CallStringList xs ->
8922 "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
8923 | CallInt i when i >= 0 -> string_of_int i
8924 | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
8925 | CallBool b -> string_of_bool b
8930 generate_lang_bindtests (
8931 fun f args -> pr " Guestfs.%s g %s;\n" f (mkargs args)
8934 pr "print_endline \"EOF\"\n"
8936 and generate_perl_bindtests () =
8937 pr "#!/usr/bin/perl -w\n";
8938 generate_header HashStyle GPLv2;
8945 my $g = Sys::Guestfs->new ();
8949 String.concat ", " (
8952 | CallString s -> "\"" ^ s ^ "\""
8953 | CallOptString None -> "undef"
8954 | CallOptString (Some s) -> sprintf "\"%s\"" s
8955 | CallStringList xs ->
8956 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
8957 | CallInt i -> string_of_int i
8958 | CallBool b -> if b then "1" else "0"
8963 generate_lang_bindtests (
8964 fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
8967 pr "print \"EOF\\n\"\n"
8969 and generate_python_bindtests () =
8970 generate_header HashStyle GPLv2;
8975 g = guestfs.GuestFS ()
8979 String.concat ", " (
8982 | CallString s -> "\"" ^ s ^ "\""
8983 | CallOptString None -> "None"
8984 | CallOptString (Some s) -> sprintf "\"%s\"" s
8985 | CallStringList xs ->
8986 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
8987 | CallInt i -> string_of_int i
8988 | CallBool b -> if b then "1" else "0"
8993 generate_lang_bindtests (
8994 fun f args -> pr "g.%s (%s)\n" f (mkargs args)
8997 pr "print \"EOF\"\n"
8999 and generate_ruby_bindtests () =
9000 generate_header HashStyle GPLv2;
9005 g = Guestfs::create()
9009 String.concat ", " (
9012 | CallString s -> "\"" ^ s ^ "\""
9013 | CallOptString None -> "nil"
9014 | CallOptString (Some s) -> sprintf "\"%s\"" s
9015 | CallStringList xs ->
9016 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9017 | CallInt i -> string_of_int i
9018 | CallBool b -> string_of_bool b
9023 generate_lang_bindtests (
9024 fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9027 pr "print \"EOF\\n\"\n"
9029 and generate_java_bindtests () =
9030 generate_header CStyle GPLv2;
9033 import com.redhat.et.libguestfs.*;
9035 public class Bindtests {
9036 public static void main (String[] argv)
9039 GuestFS g = new GuestFS ();
9043 String.concat ", " (
9046 | CallString s -> "\"" ^ s ^ "\""
9047 | CallOptString None -> "null"
9048 | CallOptString (Some s) -> sprintf "\"%s\"" s
9049 | CallStringList xs ->
9051 String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9052 | CallInt i -> string_of_int i
9053 | CallBool b -> string_of_bool b
9058 generate_lang_bindtests (
9059 fun f args -> pr " g.%s (%s);\n" f (mkargs args)
9063 System.out.println (\"EOF\");
9065 catch (Exception exn) {
9066 System.err.println (exn);
9073 and generate_haskell_bindtests () =
9074 generate_header HaskellStyle GPLv2;
9077 module Bindtests where
9078 import qualified Guestfs
9088 | CallString s -> "\"" ^ s ^ "\""
9089 | CallOptString None -> "Nothing"
9090 | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9091 | CallStringList xs ->
9092 "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9093 | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9094 | CallInt i -> string_of_int i
9095 | CallBool true -> "True"
9096 | CallBool false -> "False"
9101 generate_lang_bindtests (
9102 fun f args -> pr " Guestfs.%s g %s\n" f (mkargs args)
9105 pr " putStrLn \"EOF\"\n"
9107 (* Language-independent bindings tests - we do it this way to
9108 * ensure there is parity in testing bindings across all languages.
9110 and generate_lang_bindtests call =
9111 call "test0" [CallString "abc"; CallOptString (Some "def");
9112 CallStringList []; CallBool false;
9113 CallInt 0; CallString "123"; CallString "456"];
9114 call "test0" [CallString "abc"; CallOptString None;
9115 CallStringList []; CallBool false;
9116 CallInt 0; CallString "123"; CallString "456"];
9117 call "test0" [CallString ""; CallOptString (Some "def");
9118 CallStringList []; CallBool false;
9119 CallInt 0; CallString "123"; CallString "456"];
9120 call "test0" [CallString ""; CallOptString (Some "");
9121 CallStringList []; CallBool false;
9122 CallInt 0; CallString "123"; CallString "456"];
9123 call "test0" [CallString "abc"; CallOptString (Some "def");
9124 CallStringList ["1"]; CallBool false;
9125 CallInt 0; CallString "123"; CallString "456"];
9126 call "test0" [CallString "abc"; CallOptString (Some "def");
9127 CallStringList ["1"; "2"]; CallBool false;
9128 CallInt 0; CallString "123"; CallString "456"];
9129 call "test0" [CallString "abc"; CallOptString (Some "def");
9130 CallStringList ["1"]; CallBool true;
9131 CallInt 0; CallString "123"; CallString "456"];
9132 call "test0" [CallString "abc"; CallOptString (Some "def");
9133 CallStringList ["1"]; CallBool false;
9134 CallInt (-1); CallString "123"; CallString "456"];
9135 call "test0" [CallString "abc"; CallOptString (Some "def");
9136 CallStringList ["1"]; CallBool false;
9137 CallInt (-2); CallString "123"; CallString "456"];
9138 call "test0" [CallString "abc"; CallOptString (Some "def");
9139 CallStringList ["1"]; CallBool false;
9140 CallInt 1; CallString "123"; CallString "456"];
9141 call "test0" [CallString "abc"; CallOptString (Some "def");
9142 CallStringList ["1"]; CallBool false;
9143 CallInt 2; CallString "123"; CallString "456"];
9144 call "test0" [CallString "abc"; CallOptString (Some "def");
9145 CallStringList ["1"]; CallBool false;
9146 CallInt 4095; CallString "123"; CallString "456"];
9147 call "test0" [CallString "abc"; CallOptString (Some "def");
9148 CallStringList ["1"]; CallBool false;
9149 CallInt 0; CallString ""; CallString ""]
9151 (* XXX Add here tests of the return and error functions. *)
9153 (* This is used to generate the src/MAX_PROC_NR file which
9154 * contains the maximum procedure number, a surrogate for the
9155 * ABI version number. See src/Makefile.am for the details.
9157 and generate_max_proc_nr () =
9158 let proc_nrs = List.map (
9159 fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9160 ) daemon_functions in
9162 let max_proc_nr = List.fold_left max 0 proc_nrs in
9164 pr "%d\n" max_proc_nr
9166 let output_to filename =
9167 let filename_new = filename ^ ".new" in
9168 chan := open_out filename_new;
9173 (* Is the new file different from the current file? *)
9174 if Sys.file_exists filename && files_equal filename filename_new then
9175 Unix.unlink filename_new (* same, so skip it *)
9177 (* different, overwrite old one *)
9178 (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9179 Unix.rename filename_new filename;
9180 Unix.chmod filename 0o444;
9181 printf "written %s\n%!" filename;
9190 if not (Sys.file_exists "HACKING") then (
9192 You are probably running this from the wrong directory.
9193 Run it from the top source directory using the command
9199 let close = output_to "src/guestfs_protocol.x" in
9203 let close = output_to "src/guestfs-structs.h" in
9204 generate_structs_h ();
9207 let close = output_to "src/guestfs-actions.h" in
9208 generate_actions_h ();
9211 let close = output_to "src/guestfs-actions.c" in
9212 generate_client_actions ();
9215 let close = output_to "daemon/actions.h" in
9216 generate_daemon_actions_h ();
9219 let close = output_to "daemon/stubs.c" in
9220 generate_daemon_actions ();
9223 let close = output_to "daemon/names.c" in
9224 generate_daemon_names ();
9227 let close = output_to "capitests/tests.c" in
9231 let close = output_to "src/guestfs-bindtests.c" in
9232 generate_bindtests ();
9235 let close = output_to "fish/cmds.c" in
9236 generate_fish_cmds ();
9239 let close = output_to "fish/completion.c" in
9240 generate_fish_completion ();
9243 let close = output_to "guestfs-structs.pod" in
9244 generate_structs_pod ();
9247 let close = output_to "guestfs-actions.pod" in
9248 generate_actions_pod ();
9251 let close = output_to "guestfish-actions.pod" in
9252 generate_fish_actions_pod ();
9255 let close = output_to "ocaml/guestfs.mli" in
9256 generate_ocaml_mli ();
9259 let close = output_to "ocaml/guestfs.ml" in
9260 generate_ocaml_ml ();
9263 let close = output_to "ocaml/guestfs_c_actions.c" in
9264 generate_ocaml_c ();
9267 let close = output_to "ocaml/bindtests.ml" in
9268 generate_ocaml_bindtests ();
9271 let close = output_to "perl/Guestfs.xs" in
9272 generate_perl_xs ();
9275 let close = output_to "perl/lib/Sys/Guestfs.pm" in
9276 generate_perl_pm ();
9279 let close = output_to "perl/bindtests.pl" in
9280 generate_perl_bindtests ();
9283 let close = output_to "python/guestfs-py.c" in
9284 generate_python_c ();
9287 let close = output_to "python/guestfs.py" in
9288 generate_python_py ();
9291 let close = output_to "python/bindtests.py" in
9292 generate_python_bindtests ();
9295 let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9299 let close = output_to "ruby/bindtests.rb" in
9300 generate_ruby_bindtests ();
9303 let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9304 generate_java_java ();
9309 let cols = cols_of_struct typ in
9310 let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9311 let close = output_to filename in
9312 generate_java_struct jtyp cols;
9316 let close = output_to "java/Makefile.inc" in
9317 generate_java_makefile_inc ();
9320 let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9324 let close = output_to "java/Bindtests.java" in
9325 generate_java_bindtests ();
9328 let close = output_to "haskell/Guestfs.hs" in
9329 generate_haskell_hs ();
9332 let close = output_to "haskell/Bindtests.hs" in
9333 generate_haskell_bindtests ();
9336 let close = output_to "src/MAX_PROC_NR" in
9337 generate_max_proc_nr ();
9340 (* Always generate this file last, and unconditionally. It's used
9341 * by the Makefile to know when we must re-run the generator.
9343 let chan = open_out "src/stamp-generator" in