New commands: mkfs-b, mke2journal*, mke2fs-J*
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
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.
9  *
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.
14  *
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
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
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.
26  *
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.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
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).
50      *)
51   | RInt of string
52
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).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
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.
71      *)
72   | RConstString of string
73
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!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
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.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
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.
108      *)
109   | RHashtable of string
110
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.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
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
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
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.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | Bool of string      (* boolean *)
143   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
144     (* These are treated as filenames (simple string parameters) in
145      * the C API and bindings.  But in the RPC protocol, we transfer
146      * the actual file content up to or down from the daemon.
147      * FileIn: local machine -> daemon (in request)
148      * FileOut: daemon -> local machine (in reply)
149      * In guestfish (only), the special name "-" means read from
150      * stdin or write to stdout.
151      *)
152   | FileIn of string
153   | FileOut of string
154 (* Not implemented:
155     (* Opaque buffer which can contain arbitrary 8 bit data.
156      * In the C API, this is expressed as <char *, int> pair.
157      * Most other languages have a string type which can contain
158      * ASCII NUL.  We use whatever type is appropriate for each
159      * language.
160      * Buffers are limited by the total message size.  To transfer
161      * large blocks of data, use FileIn/FileOut parameters instead.
162      * To return an arbitrary buffer, use RBufferOut.
163      *)
164   | BufferIn of string
165 *)
166
167 type flags =
168   | ProtocolLimitWarning  (* display warning about protocol size limits *)
169   | DangerWillRobinson    (* flags particularly dangerous commands *)
170   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
171   | FishAction of string  (* call this function in guestfish *)
172   | NotInFish             (* do not export via guestfish *)
173   | NotInDocs             (* do not add this function to documentation *)
174   | DeprecatedBy of string (* function is deprecated, use .. instead *)
175
176 (* You can supply zero or as many tests as you want per API call.
177  *
178  * Note that the test environment has 3 block devices, of size 500MB,
179  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
180  * a fourth squashfs block device with some known files on it (/dev/sdd).
181  *
182  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
183  * Number of cylinders was 63 for IDE emulated disks with precisely
184  * the same size.  How exactly this is calculated is a mystery.
185  *
186  * The squashfs block device (/dev/sdd) comes from images/test.sqsh.
187  *
188  * To be able to run the tests in a reasonable amount of time,
189  * the virtual machine and block devices are reused between tests.
190  * So don't try testing kill_subprocess :-x
191  *
192  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
193  *
194  * Don't assume anything about the previous contents of the block
195  * devices.  Use 'Init*' to create some initial scenarios.
196  *
197  * You can add a prerequisite clause to any individual test.  This
198  * is a run-time check, which, if it fails, causes the test to be
199  * skipped.  Useful if testing a command which might not work on
200  * all variations of libguestfs builds.  A test that has prerequisite
201  * of 'Always' is run unconditionally.
202  *
203  * In addition, packagers can skip individual tests by setting the
204  * environment variables:     eg:
205  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
206  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
207  *)
208 type tests = (test_init * test_prereq * test) list
209 and test =
210     (* Run the command sequence and just expect nothing to fail. *)
211   | TestRun of seq
212
213     (* Run the command sequence and expect the output of the final
214      * command to be the string.
215      *)
216   | TestOutput of seq * string
217
218     (* Run the command sequence and expect the output of the final
219      * command to be the list of strings.
220      *)
221   | TestOutputList of seq * string list
222
223     (* Run the command sequence and expect the output of the final
224      * command to be the list of block devices (could be either
225      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
226      * character of each string).
227      *)
228   | TestOutputListOfDevices of seq * string list
229
230     (* Run the command sequence and expect the output of the final
231      * command to be the integer.
232      *)
233   | TestOutputInt of seq * int
234
235     (* Run the command sequence and expect the output of the final
236      * command to be <op> <int>, eg. ">=", "1".
237      *)
238   | TestOutputIntOp of seq * string * int
239
240     (* Run the command sequence and expect the output of the final
241      * command to be a true value (!= 0 or != NULL).
242      *)
243   | TestOutputTrue of seq
244
245     (* Run the command sequence and expect the output of the final
246      * command to be a false value (== 0 or == NULL, but not an error).
247      *)
248   | TestOutputFalse of seq
249
250     (* Run the command sequence and expect the output of the final
251      * command to be a list of the given length (but don't care about
252      * content).
253      *)
254   | TestOutputLength of seq * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a buffer (RBufferOut), ie. string + size.
258      *)
259   | TestOutputBuffer of seq * string
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a structure.
263      *)
264   | TestOutputStruct of seq * test_field_compare list
265
266     (* Run the command sequence and expect the final command (only)
267      * to fail.
268      *)
269   | TestLastFail of seq
270
271 and test_field_compare =
272   | CompareWithInt of string * int
273   | CompareWithIntOp of string * string * int
274   | CompareWithString of string * string
275   | CompareFieldsIntEq of string * string
276   | CompareFieldsStrEq of string * string
277
278 (* Test prerequisites. *)
279 and test_prereq =
280     (* Test always runs. *)
281   | Always
282
283     (* Test is currently disabled - eg. it fails, or it tests some
284      * unimplemented feature.
285      *)
286   | Disabled
287
288     (* 'string' is some C code (a function body) that should return
289      * true or false.  The test will run if the code returns true.
290      *)
291   | If of string
292
293     (* As for 'If' but the test runs _unless_ the code returns true. *)
294   | Unless of string
295
296 (* Some initial scenarios for testing. *)
297 and test_init =
298     (* Do nothing, block devices could contain random stuff including
299      * LVM PVs, and some filesystems might be mounted.  This is usually
300      * a bad idea.
301      *)
302   | InitNone
303
304     (* Block devices are empty and no filesystems are mounted. *)
305   | InitEmpty
306
307     (* /dev/sda contains a single partition /dev/sda1, with random
308      * content.  /dev/sdb and /dev/sdc may have random content.
309      * No LVM.
310      *)
311   | InitPartition
312
313     (* /dev/sda contains a single partition /dev/sda1, which is formatted
314      * as ext2, empty [except for lost+found] and mounted on /.
315      * /dev/sdb and /dev/sdc may have random content.
316      * No LVM.
317      *)
318   | InitBasicFS
319
320     (* /dev/sda:
321      *   /dev/sda1 (is a PV):
322      *     /dev/VG/LV (size 8MB):
323      *       formatted as ext2, empty [except for lost+found], mounted on /
324      * /dev/sdb and /dev/sdc may have random content.
325      *)
326   | InitBasicFSonLVM
327
328     (* /dev/sdd (the squashfs, see images/ directory in source)
329      * is mounted on /
330      *)
331   | InitSquashFS
332
333 (* Sequence of commands for testing. *)
334 and seq = cmd list
335 and cmd = string list
336
337 (* Note about long descriptions: When referring to another
338  * action, use the format C<guestfs_other> (ie. the full name of
339  * the C function).  This will be replaced as appropriate in other
340  * language bindings.
341  *
342  * Apart from that, long descriptions are just perldoc paragraphs.
343  *)
344
345 (* Generate a random UUID (used in tests). *)
346 let uuidgen () =
347   let chan = Unix.open_process_in "uuidgen" in
348   let uuid = input_line chan in
349   (match Unix.close_process_in chan with
350    | Unix.WEXITED 0 -> ()
351    | Unix.WEXITED _ ->
352        failwith "uuidgen: process exited with non-zero status"
353    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
354        failwith "uuidgen: process signalled or stopped by signal"
355   );
356   uuid
357
358 (* These test functions are used in the language binding tests. *)
359
360 let test_all_args = [
361   String "str";
362   OptString "optstr";
363   StringList "strlist";
364   Bool "b";
365   Int "integer";
366   FileIn "filein";
367   FileOut "fileout";
368 ]
369
370 let test_all_rets = [
371   (* except for RErr, which is tested thoroughly elsewhere *)
372   "test0rint",         RInt "valout";
373   "test0rint64",       RInt64 "valout";
374   "test0rbool",        RBool "valout";
375   "test0rconststring", RConstString "valout";
376   "test0rconstoptstring", RConstOptString "valout";
377   "test0rstring",      RString "valout";
378   "test0rstringlist",  RStringList "valout";
379   "test0rstruct",      RStruct ("valout", "lvm_pv");
380   "test0rstructlist",  RStructList ("valout", "lvm_pv");
381   "test0rhashtable",   RHashtable "valout";
382 ]
383
384 let test_functions = [
385   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
386    [],
387    "internal test function - do not use",
388    "\
389 This is an internal test function which is used to test whether
390 the automatically generated bindings can handle every possible
391 parameter type correctly.
392
393 It echos the contents of each parameter to stdout.
394
395 You probably don't want to call this function.");
396 ] @ List.flatten (
397   List.map (
398     fun (name, ret) ->
399       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
400         [],
401         "internal test function - do not use",
402         "\
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 return type correctly.
406
407 It converts string C<val> to the return type.
408
409 You probably don't want to call this function.");
410        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
411         [],
412         "internal test function - do not use",
413         "\
414 This is an internal test function which is used to test whether
415 the automatically generated bindings can handle every possible
416 return type correctly.
417
418 This function always returns an error.
419
420 You probably don't want to call this function.")]
421   ) test_all_rets
422 )
423
424 (* non_daemon_functions are any functions which don't get processed
425  * in the daemon, eg. functions for setting and getting local
426  * configuration values.
427  *)
428
429 let non_daemon_functions = test_functions @ [
430   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
431    [],
432    "launch the qemu subprocess",
433    "\
434 Internally libguestfs is implemented by running a virtual machine
435 using L<qemu(1)>.
436
437 You should call this after configuring the handle
438 (eg. adding drives) but before performing any actions.");
439
440   ("wait_ready", (RErr, []), -1, [NotInFish],
441    [],
442    "wait until the qemu subprocess launches",
443    "\
444 Internally libguestfs is implemented by running a virtual machine
445 using L<qemu(1)>.
446
447 You should call this after C<guestfs_launch> to wait for the launch
448 to complete.");
449
450   ("kill_subprocess", (RErr, []), -1, [],
451    [],
452    "kill the qemu subprocess",
453    "\
454 This kills the qemu subprocess.  You should never need to call this.");
455
456   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
457    [],
458    "add an image to examine or modify",
459    "\
460 This function adds a virtual machine disk image C<filename> to the
461 guest.  The first time you call this function, the disk appears as IDE
462 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
463 so on.
464
465 You don't necessarily need to be root when using libguestfs.  However
466 you obviously do need sufficient permissions to access the filename
467 for whatever operations you want to perform (ie. read access if you
468 just want to read the image or write access if you want to modify the
469 image).
470
471 This is equivalent to the qemu parameter
472 C<-drive file=filename,cache=off,if=...>.
473 C<cache=off> is omitted in cases where it is not supported by
474 the underlying filesystem.
475
476 Note that this call checks for the existence of C<filename>.  This
477 stops you from specifying other types of drive which are supported
478 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
479 the general C<guestfs_config> call instead.");
480
481   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
482    [],
483    "add a CD-ROM disk image to examine",
484    "\
485 This function adds a virtual CD-ROM disk image to the guest.
486
487 This is equivalent to the qemu parameter C<-cdrom filename>.
488
489 Note that this call checks for the existence of C<filename>.  This
490 stops you from specifying other types of drive which are supported
491 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
492 the general C<guestfs_config> call instead.");
493
494   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
495    [],
496    "add a drive in snapshot mode (read-only)",
497    "\
498 This adds a drive in snapshot mode, making it effectively
499 read-only.
500
501 Note that writes to the device are allowed, and will be seen for
502 the duration of the guestfs handle, but they are written
503 to a temporary file which is discarded as soon as the guestfs
504 handle is closed.  We don't currently have any method to enable
505 changes to be committed, although qemu can support this.
506
507 This is equivalent to the qemu parameter
508 C<-drive file=filename,snapshot=on,if=...>.
509
510 Note that this call checks for the existence of C<filename>.  This
511 stops you from specifying other types of drive which are supported
512 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
513 the general C<guestfs_config> call instead.");
514
515   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
516    [],
517    "add qemu parameters",
518    "\
519 This can be used to add arbitrary qemu command line parameters
520 of the form C<-param value>.  Actually it's not quite arbitrary - we
521 prevent you from setting some parameters which would interfere with
522 parameters that we use.
523
524 The first character of C<param> string must be a C<-> (dash).
525
526 C<value> can be NULL.");
527
528   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
529    [],
530    "set the qemu binary",
531    "\
532 Set the qemu binary that we will use.
533
534 The default is chosen when the library was compiled by the
535 configure script.
536
537 You can also override this by setting the C<LIBGUESTFS_QEMU>
538 environment variable.
539
540 Setting C<qemu> to C<NULL> restores the default qemu binary.");
541
542   ("get_qemu", (RConstString "qemu", []), -1, [],
543    [InitNone, Always, TestRun (
544       [["get_qemu"]])],
545    "get the qemu binary",
546    "\
547 Return the current qemu binary.
548
549 This is always non-NULL.  If it wasn't set already, then this will
550 return the default qemu binary name.");
551
552   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
553    [],
554    "set the search path",
555    "\
556 Set the path that libguestfs searches for kernel and initrd.img.
557
558 The default is C<$libdir/guestfs> unless overridden by setting
559 C<LIBGUESTFS_PATH> environment variable.
560
561 Setting C<path> to C<NULL> restores the default path.");
562
563   ("get_path", (RConstString "path", []), -1, [],
564    [InitNone, Always, TestRun (
565       [["get_path"]])],
566    "get the search path",
567    "\
568 Return the current search path.
569
570 This is always non-NULL.  If it wasn't set already, then this will
571 return the default path.");
572
573   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
574    [],
575    "add options to kernel command line",
576    "\
577 This function is used to add additional options to the
578 guest kernel command line.
579
580 The default is C<NULL> unless overridden by setting
581 C<LIBGUESTFS_APPEND> environment variable.
582
583 Setting C<append> to C<NULL> means I<no> additional options
584 are passed (libguestfs always adds a few of its own).");
585
586   ("get_append", (RConstOptString "append", []), -1, [],
587    (* This cannot be tested with the current framework.  The
588     * function can return NULL in normal operations, which the
589     * test framework interprets as an error.
590     *)
591    [],
592    "get the additional kernel options",
593    "\
594 Return the additional kernel options which are added to the
595 guest kernel command line.
596
597 If C<NULL> then no options are added.");
598
599   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
600    [],
601    "set autosync mode",
602    "\
603 If C<autosync> is true, this enables autosync.  Libguestfs will make a
604 best effort attempt to run C<guestfs_umount_all> followed by
605 C<guestfs_sync> when the handle is closed
606 (also if the program exits without closing handles).
607
608 This is disabled by default (except in guestfish where it is
609 enabled by default).");
610
611   ("get_autosync", (RBool "autosync", []), -1, [],
612    [InitNone, Always, TestRun (
613       [["get_autosync"]])],
614    "get autosync mode",
615    "\
616 Get the autosync flag.");
617
618   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
619    [],
620    "set verbose mode",
621    "\
622 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
623
624 Verbose messages are disabled unless the environment variable
625 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
626
627   ("get_verbose", (RBool "verbose", []), -1, [],
628    [],
629    "get verbose mode",
630    "\
631 This returns the verbose messages flag.");
632
633   ("is_ready", (RBool "ready", []), -1, [],
634    [InitNone, Always, TestOutputTrue (
635       [["is_ready"]])],
636    "is ready to accept commands",
637    "\
638 This returns true iff this handle is ready to accept commands
639 (in the C<READY> state).
640
641 For more information on states, see L<guestfs(3)>.");
642
643   ("is_config", (RBool "config", []), -1, [],
644    [InitNone, Always, TestOutputFalse (
645       [["is_config"]])],
646    "is in configuration state",
647    "\
648 This returns true iff this handle is being configured
649 (in the C<CONFIG> state).
650
651 For more information on states, see L<guestfs(3)>.");
652
653   ("is_launching", (RBool "launching", []), -1, [],
654    [InitNone, Always, TestOutputFalse (
655       [["is_launching"]])],
656    "is launching subprocess",
657    "\
658 This returns true iff this handle is launching the subprocess
659 (in the C<LAUNCHING> state).
660
661 For more information on states, see L<guestfs(3)>.");
662
663   ("is_busy", (RBool "busy", []), -1, [],
664    [InitNone, Always, TestOutputFalse (
665       [["is_busy"]])],
666    "is busy processing a command",
667    "\
668 This returns true iff this handle is busy processing a command
669 (in the C<BUSY> state).
670
671 For more information on states, see L<guestfs(3)>.");
672
673   ("get_state", (RInt "state", []), -1, [],
674    [],
675    "get the current state",
676    "\
677 This returns the current state as an opaque integer.  This is
678 only useful for printing debug and internal error messages.
679
680 For more information on states, see L<guestfs(3)>.");
681
682   ("set_busy", (RErr, []), -1, [NotInFish],
683    [],
684    "set state to busy",
685    "\
686 This sets the state to C<BUSY>.  This is only used when implementing
687 actions using the low-level API.
688
689 For more information on states, see L<guestfs(3)>.");
690
691   ("set_ready", (RErr, []), -1, [NotInFish],
692    [],
693    "set state to ready",
694    "\
695 This sets the state to C<READY>.  This is only used when implementing
696 actions using the low-level API.
697
698 For more information on states, see L<guestfs(3)>.");
699
700   ("end_busy", (RErr, []), -1, [NotInFish],
701    [],
702    "leave the busy state",
703    "\
704 This sets the state to C<READY>, or if in C<CONFIG> then it leaves the
705 state as is.  This is only used when implementing
706 actions using the low-level API.
707
708 For more information on states, see L<guestfs(3)>.");
709
710   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
711    [InitNone, Always, TestOutputInt (
712       [["set_memsize"; "500"];
713        ["get_memsize"]], 500)],
714    "set memory allocated to the qemu subprocess",
715    "\
716 This sets the memory size in megabytes allocated to the
717 qemu subprocess.  This only has any effect if called before
718 C<guestfs_launch>.
719
720 You can also change this by setting the environment
721 variable C<LIBGUESTFS_MEMSIZE> before the handle is
722 created.
723
724 For more information on the architecture of libguestfs,
725 see L<guestfs(3)>.");
726
727   ("get_memsize", (RInt "memsize", []), -1, [],
728    [InitNone, Always, TestOutputIntOp (
729       [["get_memsize"]], ">=", 256)],
730    "get memory allocated to the qemu subprocess",
731    "\
732 This gets the memory size in megabytes allocated to the
733 qemu subprocess.
734
735 If C<guestfs_set_memsize> was not called
736 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
737 then this returns the compiled-in default value for memsize.
738
739 For more information on the architecture of libguestfs,
740 see L<guestfs(3)>.");
741
742   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
743    [InitNone, Always, TestOutputIntOp (
744       [["get_pid"]], ">=", 1)],
745    "get PID of qemu subprocess",
746    "\
747 Return the process ID of the qemu subprocess.  If there is no
748 qemu subprocess, then this will return an error.
749
750 This is an internal call used for debugging and testing.");
751
752   ("version", (RStruct ("version", "version"), []), -1, [],
753    [InitNone, Always, TestOutputStruct (
754       [["version"]], [CompareWithInt ("major", 1)])],
755    "get the library version number",
756    "\
757 Return the libguestfs version number that the program is linked
758 against.
759
760 Note that because of dynamic linking this is not necessarily
761 the version of libguestfs that you compiled against.  You can
762 compile the program, and then at runtime dynamically link
763 against a completely different C<libguestfs.so> library.
764
765 This call was added in version C<1.0.58>.  In previous
766 versions of libguestfs there was no way to get the version
767 number.  From C code you can use ELF weak linking tricks to find out if
768 this symbol exists (if it doesn't, then it's an earlier version).
769
770 The call returns a structure with four elements.  The first
771 three (C<major>, C<minor> and C<release>) are numbers and
772 correspond to the usual version triplet.  The fourth element
773 (C<extra>) is a string and is normally empty, but may be
774 used for distro-specific information.
775
776 To construct the original version string:
777 C<$major.$minor.$release$extra>
778
779 I<Note:> Don't use this call to test for availability
780 of features.  Distro backports makes this unreliable.");
781
782   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
783    [InitNone, Always, TestOutputTrue (
784       [["set_selinux"; "true"];
785        ["get_selinux"]])],
786    "set SELinux enabled or disabled at appliance boot",
787    "\
788 This sets the selinux flag that is passed to the appliance
789 at boot time.  The default is C<selinux=0> (disabled).
790
791 Note that if SELinux is enabled, it is always in
792 Permissive mode (C<enforcing=0>).
793
794 For more information on the architecture of libguestfs,
795 see L<guestfs(3)>.");
796
797   ("get_selinux", (RBool "selinux", []), -1, [],
798    [],
799    "get SELinux enabled flag",
800    "\
801 This returns the current setting of the selinux flag which
802 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
803
804 For more information on the architecture of libguestfs,
805 see L<guestfs(3)>.");
806
807 ]
808
809 (* daemon_functions are any functions which cause some action
810  * to take place in the daemon.
811  *)
812
813 let daemon_functions = [
814   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
815    [InitEmpty, Always, TestOutput (
816       [["sfdiskM"; "/dev/sda"; ","];
817        ["mkfs"; "ext2"; "/dev/sda1"];
818        ["mount"; "/dev/sda1"; "/"];
819        ["write_file"; "/new"; "new file contents"; "0"];
820        ["cat"; "/new"]], "new file contents")],
821    "mount a guest disk at a position in the filesystem",
822    "\
823 Mount a guest disk at a position in the filesystem.  Block devices
824 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
825 the guest.  If those block devices contain partitions, they will have
826 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
827 names can be used.
828
829 The rules are the same as for L<mount(2)>:  A filesystem must
830 first be mounted on C</> before others can be mounted.  Other
831 filesystems can only be mounted on directories which already
832 exist.
833
834 The mounted filesystem is writable, if we have sufficient permissions
835 on the underlying device.
836
837 The filesystem options C<sync> and C<noatime> are set with this
838 call, in order to improve reliability.");
839
840   ("sync", (RErr, []), 2, [],
841    [ InitEmpty, Always, TestRun [["sync"]]],
842    "sync disks, writes are flushed through to the disk image",
843    "\
844 This syncs the disk, so that any writes are flushed through to the
845 underlying disk image.
846
847 You should always call this if you have modified a disk image, before
848 closing the handle.");
849
850   ("touch", (RErr, [Pathname "path"]), 3, [],
851    [InitBasicFS, Always, TestOutputTrue (
852       [["touch"; "/new"];
853        ["exists"; "/new"]])],
854    "update file timestamps or create a new file",
855    "\
856 Touch acts like the L<touch(1)> command.  It can be used to
857 update the timestamps on a file, or, if the file does not exist,
858 to create a new zero-length file.");
859
860   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
861    [InitSquashFS, Always, TestOutput (
862       [["cat"; "/known-2"]], "abcdef\n")],
863    "list the contents of a file",
864    "\
865 Return the contents of the file named C<path>.
866
867 Note that this function cannot correctly handle binary files
868 (specifically, files containing C<\\0> character which is treated
869 as end of string).  For those you need to use the C<guestfs_read_file>
870 or C<guestfs_download> functions which have a more complex interface.");
871
872   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
873    [], (* XXX Tricky to test because it depends on the exact format
874         * of the 'ls -l' command, which changes between F10 and F11.
875         *)
876    "list the files in a directory (long format)",
877    "\
878 List the files in C<directory> (relative to the root directory,
879 there is no cwd) in the format of 'ls -la'.
880
881 This command is mostly useful for interactive sessions.  It
882 is I<not> intended that you try to parse the output string.");
883
884   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
885    [InitBasicFS, Always, TestOutputList (
886       [["touch"; "/new"];
887        ["touch"; "/newer"];
888        ["touch"; "/newest"];
889        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
890    "list the files in a directory",
891    "\
892 List the files in C<directory> (relative to the root directory,
893 there is no cwd).  The '.' and '..' entries are not returned, but
894 hidden files are shown.
895
896 This command is mostly useful for interactive sessions.  Programs
897 should probably use C<guestfs_readdir> instead.");
898
899   ("list_devices", (RStringList "devices", []), 7, [],
900    [InitEmpty, Always, TestOutputListOfDevices (
901       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
902    "list the block devices",
903    "\
904 List all the block devices.
905
906 The full block device names are returned, eg. C</dev/sda>");
907
908   ("list_partitions", (RStringList "partitions", []), 8, [],
909    [InitBasicFS, Always, TestOutputListOfDevices (
910       [["list_partitions"]], ["/dev/sda1"]);
911     InitEmpty, Always, TestOutputListOfDevices (
912       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
913        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
914    "list the partitions",
915    "\
916 List all the partitions detected on all block devices.
917
918 The full partition device names are returned, eg. C</dev/sda1>
919
920 This does not return logical volumes.  For that you will need to
921 call C<guestfs_lvs>.");
922
923   ("pvs", (RStringList "physvols", []), 9, [],
924    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
925       [["pvs"]], ["/dev/sda1"]);
926     InitEmpty, Always, TestOutputListOfDevices (
927       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
928        ["pvcreate"; "/dev/sda1"];
929        ["pvcreate"; "/dev/sda2"];
930        ["pvcreate"; "/dev/sda3"];
931        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
932    "list the LVM physical volumes (PVs)",
933    "\
934 List all the physical volumes detected.  This is the equivalent
935 of the L<pvs(8)> command.
936
937 This returns a list of just the device names that contain
938 PVs (eg. C</dev/sda2>).
939
940 See also C<guestfs_pvs_full>.");
941
942   ("vgs", (RStringList "volgroups", []), 10, [],
943    [InitBasicFSonLVM, Always, TestOutputList (
944       [["vgs"]], ["VG"]);
945     InitEmpty, Always, TestOutputList (
946       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
947        ["pvcreate"; "/dev/sda1"];
948        ["pvcreate"; "/dev/sda2"];
949        ["pvcreate"; "/dev/sda3"];
950        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
951        ["vgcreate"; "VG2"; "/dev/sda3"];
952        ["vgs"]], ["VG1"; "VG2"])],
953    "list the LVM volume groups (VGs)",
954    "\
955 List all the volumes groups detected.  This is the equivalent
956 of the L<vgs(8)> command.
957
958 This returns a list of just the volume group names that were
959 detected (eg. C<VolGroup00>).
960
961 See also C<guestfs_vgs_full>.");
962
963   ("lvs", (RStringList "logvols", []), 11, [],
964    [InitBasicFSonLVM, Always, TestOutputList (
965       [["lvs"]], ["/dev/VG/LV"]);
966     InitEmpty, Always, TestOutputList (
967       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
968        ["pvcreate"; "/dev/sda1"];
969        ["pvcreate"; "/dev/sda2"];
970        ["pvcreate"; "/dev/sda3"];
971        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
972        ["vgcreate"; "VG2"; "/dev/sda3"];
973        ["lvcreate"; "LV1"; "VG1"; "50"];
974        ["lvcreate"; "LV2"; "VG1"; "50"];
975        ["lvcreate"; "LV3"; "VG2"; "50"];
976        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
977    "list the LVM logical volumes (LVs)",
978    "\
979 List all the logical volumes detected.  This is the equivalent
980 of the L<lvs(8)> command.
981
982 This returns a list of the logical volume device names
983 (eg. C</dev/VolGroup00/LogVol00>).
984
985 See also C<guestfs_lvs_full>.");
986
987   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
988    [], (* XXX how to test? *)
989    "list the LVM physical volumes (PVs)",
990    "\
991 List all the physical volumes detected.  This is the equivalent
992 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
993
994   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
995    [], (* XXX how to test? *)
996    "list the LVM volume groups (VGs)",
997    "\
998 List all the volumes groups detected.  This is the equivalent
999 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1000
1001   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1002    [], (* XXX how to test? *)
1003    "list the LVM logical volumes (LVs)",
1004    "\
1005 List all the logical volumes detected.  This is the equivalent
1006 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1007
1008   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1009    [InitSquashFS, Always, TestOutputList (
1010       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1011     InitSquashFS, Always, TestOutputList (
1012       [["read_lines"; "/empty"]], [])],
1013    "read file as lines",
1014    "\
1015 Return the contents of the file named C<path>.
1016
1017 The file contents are returned as a list of lines.  Trailing
1018 C<LF> and C<CRLF> character sequences are I<not> returned.
1019
1020 Note that this function cannot correctly handle binary files
1021 (specifically, files containing C<\\0> character which is treated
1022 as end of line).  For those you need to use the C<guestfs_read_file>
1023 function which has a more complex interface.");
1024
1025   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1026    [], (* XXX Augeas code needs tests. *)
1027    "create a new Augeas handle",
1028    "\
1029 Create a new Augeas handle for editing configuration files.
1030 If there was any previous Augeas handle associated with this
1031 guestfs session, then it is closed.
1032
1033 You must call this before using any other C<guestfs_aug_*>
1034 commands.
1035
1036 C<root> is the filesystem root.  C<root> must not be NULL,
1037 use C</> instead.
1038
1039 The flags are the same as the flags defined in
1040 E<lt>augeas.hE<gt>, the logical I<or> of the following
1041 integers:
1042
1043 =over 4
1044
1045 =item C<AUG_SAVE_BACKUP> = 1
1046
1047 Keep the original file with a C<.augsave> extension.
1048
1049 =item C<AUG_SAVE_NEWFILE> = 2
1050
1051 Save changes into a file with extension C<.augnew>, and
1052 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1053
1054 =item C<AUG_TYPE_CHECK> = 4
1055
1056 Typecheck lenses (can be expensive).
1057
1058 =item C<AUG_NO_STDINC> = 8
1059
1060 Do not use standard load path for modules.
1061
1062 =item C<AUG_SAVE_NOOP> = 16
1063
1064 Make save a no-op, just record what would have been changed.
1065
1066 =item C<AUG_NO_LOAD> = 32
1067
1068 Do not load the tree in C<guestfs_aug_init>.
1069
1070 =back
1071
1072 To close the handle, you can call C<guestfs_aug_close>.
1073
1074 To find out more about Augeas, see L<http://augeas.net/>.");
1075
1076   ("aug_close", (RErr, []), 26, [],
1077    [], (* XXX Augeas code needs tests. *)
1078    "close the current Augeas handle",
1079    "\
1080 Close the current Augeas handle and free up any resources
1081 used by it.  After calling this, you have to call
1082 C<guestfs_aug_init> again before you can use any other
1083 Augeas functions.");
1084
1085   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1086    [], (* XXX Augeas code needs tests. *)
1087    "define an Augeas variable",
1088    "\
1089 Defines an Augeas variable C<name> whose value is the result
1090 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1091 undefined.
1092
1093 On success this returns the number of nodes in C<expr>, or
1094 C<0> if C<expr> evaluates to something which is not a nodeset.");
1095
1096   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1097    [], (* XXX Augeas code needs tests. *)
1098    "define an Augeas node",
1099    "\
1100 Defines a variable C<name> whose value is the result of
1101 evaluating C<expr>.
1102
1103 If C<expr> evaluates to an empty nodeset, a node is created,
1104 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1105 C<name> will be the nodeset containing that single node.
1106
1107 On success this returns a pair containing the
1108 number of nodes in the nodeset, and a boolean flag
1109 if a node was created.");
1110
1111   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1112    [], (* XXX Augeas code needs tests. *)
1113    "look up the value of an Augeas path",
1114    "\
1115 Look up the value associated with C<path>.  If C<path>
1116 matches exactly one node, the C<value> is returned.");
1117
1118   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1119    [], (* XXX Augeas code needs tests. *)
1120    "set Augeas path to value",
1121    "\
1122 Set the value associated with C<path> to C<value>.");
1123
1124   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1125    [], (* XXX Augeas code needs tests. *)
1126    "insert a sibling Augeas node",
1127    "\
1128 Create a new sibling C<label> for C<path>, inserting it into
1129 the tree before or after C<path> (depending on the boolean
1130 flag C<before>).
1131
1132 C<path> must match exactly one existing node in the tree, and
1133 C<label> must be a label, ie. not contain C</>, C<*> or end
1134 with a bracketed index C<[N]>.");
1135
1136   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1137    [], (* XXX Augeas code needs tests. *)
1138    "remove an Augeas path",
1139    "\
1140 Remove C<path> and all of its children.
1141
1142 On success this returns the number of entries which were removed.");
1143
1144   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1145    [], (* XXX Augeas code needs tests. *)
1146    "move Augeas node",
1147    "\
1148 Move the node C<src> to C<dest>.  C<src> must match exactly
1149 one node.  C<dest> is overwritten if it exists.");
1150
1151   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1152    [], (* XXX Augeas code needs tests. *)
1153    "return Augeas nodes which match augpath",
1154    "\
1155 Returns a list of paths which match the path expression C<path>.
1156 The returned paths are sufficiently qualified so that they match
1157 exactly one node in the current tree.");
1158
1159   ("aug_save", (RErr, []), 25, [],
1160    [], (* XXX Augeas code needs tests. *)
1161    "write all pending Augeas changes to disk",
1162    "\
1163 This writes all pending changes to disk.
1164
1165 The flags which were passed to C<guestfs_aug_init> affect exactly
1166 how files are saved.");
1167
1168   ("aug_load", (RErr, []), 27, [],
1169    [], (* XXX Augeas code needs tests. *)
1170    "load files into the tree",
1171    "\
1172 Load files into the tree.
1173
1174 See C<aug_load> in the Augeas documentation for the full gory
1175 details.");
1176
1177   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1178    [], (* XXX Augeas code needs tests. *)
1179    "list Augeas nodes under augpath",
1180    "\
1181 This is just a shortcut for listing C<guestfs_aug_match>
1182 C<path/*> and sorting the resulting nodes into alphabetical order.");
1183
1184   ("rm", (RErr, [Pathname "path"]), 29, [],
1185    [InitBasicFS, Always, TestRun
1186       [["touch"; "/new"];
1187        ["rm"; "/new"]];
1188     InitBasicFS, Always, TestLastFail
1189       [["rm"; "/new"]];
1190     InitBasicFS, Always, TestLastFail
1191       [["mkdir"; "/new"];
1192        ["rm"; "/new"]]],
1193    "remove a file",
1194    "\
1195 Remove the single file C<path>.");
1196
1197   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1198    [InitBasicFS, Always, TestRun
1199       [["mkdir"; "/new"];
1200        ["rmdir"; "/new"]];
1201     InitBasicFS, Always, TestLastFail
1202       [["rmdir"; "/new"]];
1203     InitBasicFS, Always, TestLastFail
1204       [["touch"; "/new"];
1205        ["rmdir"; "/new"]]],
1206    "remove a directory",
1207    "\
1208 Remove the single directory C<path>.");
1209
1210   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1211    [InitBasicFS, Always, TestOutputFalse
1212       [["mkdir"; "/new"];
1213        ["mkdir"; "/new/foo"];
1214        ["touch"; "/new/foo/bar"];
1215        ["rm_rf"; "/new"];
1216        ["exists"; "/new"]]],
1217    "remove a file or directory recursively",
1218    "\
1219 Remove the file or directory C<path>, recursively removing the
1220 contents if its a directory.  This is like the C<rm -rf> shell
1221 command.");
1222
1223   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1224    [InitBasicFS, Always, TestOutputTrue
1225       [["mkdir"; "/new"];
1226        ["is_dir"; "/new"]];
1227     InitBasicFS, Always, TestLastFail
1228       [["mkdir"; "/new/foo/bar"]]],
1229    "create a directory",
1230    "\
1231 Create a directory named C<path>.");
1232
1233   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1234    [InitBasicFS, Always, TestOutputTrue
1235       [["mkdir_p"; "/new/foo/bar"];
1236        ["is_dir"; "/new/foo/bar"]];
1237     InitBasicFS, Always, TestOutputTrue
1238       [["mkdir_p"; "/new/foo/bar"];
1239        ["is_dir"; "/new/foo"]];
1240     InitBasicFS, Always, TestOutputTrue
1241       [["mkdir_p"; "/new/foo/bar"];
1242        ["is_dir"; "/new"]];
1243     (* Regression tests for RHBZ#503133: *)
1244     InitBasicFS, Always, TestRun
1245       [["mkdir"; "/new"];
1246        ["mkdir_p"; "/new"]];
1247     InitBasicFS, Always, TestLastFail
1248       [["touch"; "/new"];
1249        ["mkdir_p"; "/new"]]],
1250    "create a directory and parents",
1251    "\
1252 Create a directory named C<path>, creating any parent directories
1253 as necessary.  This is like the C<mkdir -p> shell command.");
1254
1255   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1256    [], (* XXX Need stat command to test *)
1257    "change file mode",
1258    "\
1259 Change the mode (permissions) of C<path> to C<mode>.  Only
1260 numeric modes are supported.");
1261
1262   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1263    [], (* XXX Need stat command to test *)
1264    "change file owner and group",
1265    "\
1266 Change the file owner to C<owner> and group to C<group>.
1267
1268 Only numeric uid and gid are supported.  If you want to use
1269 names, you will need to locate and parse the password file
1270 yourself (Augeas support makes this relatively easy).");
1271
1272   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1273    [InitSquashFS, Always, TestOutputTrue (
1274       [["exists"; "/empty"]]);
1275     InitSquashFS, Always, TestOutputTrue (
1276       [["exists"; "/directory"]])],
1277    "test if file or directory exists",
1278    "\
1279 This returns C<true> if and only if there is a file, directory
1280 (or anything) with the given C<path> name.
1281
1282 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1283
1284   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1285    [InitSquashFS, Always, TestOutputTrue (
1286       [["is_file"; "/known-1"]]);
1287     InitSquashFS, Always, TestOutputFalse (
1288       [["is_file"; "/directory"]])],
1289    "test if file exists",
1290    "\
1291 This returns C<true> if and only if there is a file
1292 with the given C<path> name.  Note that it returns false for
1293 other objects like directories.
1294
1295 See also C<guestfs_stat>.");
1296
1297   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1298    [InitSquashFS, Always, TestOutputFalse (
1299       [["is_dir"; "/known-3"]]);
1300     InitSquashFS, Always, TestOutputTrue (
1301       [["is_dir"; "/directory"]])],
1302    "test if file exists",
1303    "\
1304 This returns C<true> if and only if there is a directory
1305 with the given C<path> name.  Note that it returns false for
1306 other objects like files.
1307
1308 See also C<guestfs_stat>.");
1309
1310   ("pvcreate", (RErr, [Device "device"]), 39, [],
1311    [InitEmpty, Always, TestOutputListOfDevices (
1312       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1313        ["pvcreate"; "/dev/sda1"];
1314        ["pvcreate"; "/dev/sda2"];
1315        ["pvcreate"; "/dev/sda3"];
1316        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1317    "create an LVM physical volume",
1318    "\
1319 This creates an LVM physical volume on the named C<device>,
1320 where C<device> should usually be a partition name such
1321 as C</dev/sda1>.");
1322
1323   ("vgcreate", (RErr, [String "volgroup"; StringList "physvols"]), 40, [],
1324    [InitEmpty, Always, TestOutputList (
1325       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1326        ["pvcreate"; "/dev/sda1"];
1327        ["pvcreate"; "/dev/sda2"];
1328        ["pvcreate"; "/dev/sda3"];
1329        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1330        ["vgcreate"; "VG2"; "/dev/sda3"];
1331        ["vgs"]], ["VG1"; "VG2"])],
1332    "create an LVM volume group",
1333    "\
1334 This creates an LVM volume group called C<volgroup>
1335 from the non-empty list of physical volumes C<physvols>.");
1336
1337   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1338    [InitEmpty, Always, TestOutputList (
1339       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1340        ["pvcreate"; "/dev/sda1"];
1341        ["pvcreate"; "/dev/sda2"];
1342        ["pvcreate"; "/dev/sda3"];
1343        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1344        ["vgcreate"; "VG2"; "/dev/sda3"];
1345        ["lvcreate"; "LV1"; "VG1"; "50"];
1346        ["lvcreate"; "LV2"; "VG1"; "50"];
1347        ["lvcreate"; "LV3"; "VG2"; "50"];
1348        ["lvcreate"; "LV4"; "VG2"; "50"];
1349        ["lvcreate"; "LV5"; "VG2"; "50"];
1350        ["lvs"]],
1351       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1352        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1353    "create an LVM volume group",
1354    "\
1355 This creates an LVM volume group called C<logvol>
1356 on the volume group C<volgroup>, with C<size> megabytes.");
1357
1358   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1359    [InitEmpty, Always, TestOutput (
1360       [["sfdiskM"; "/dev/sda"; ","];
1361        ["mkfs"; "ext2"; "/dev/sda1"];
1362        ["mount"; "/dev/sda1"; "/"];
1363        ["write_file"; "/new"; "new file contents"; "0"];
1364        ["cat"; "/new"]], "new file contents")],
1365    "make a filesystem",
1366    "\
1367 This creates a filesystem on C<device> (usually a partition
1368 or LVM logical volume).  The filesystem type is C<fstype>, for
1369 example C<ext3>.");
1370
1371   ("sfdisk", (RErr, [Device "device";
1372                      Int "cyls"; Int "heads"; Int "sectors";
1373                      StringList "lines"]), 43, [DangerWillRobinson],
1374    [],
1375    "create partitions on a block device",
1376    "\
1377 This is a direct interface to the L<sfdisk(8)> program for creating
1378 partitions on block devices.
1379
1380 C<device> should be a block device, for example C</dev/sda>.
1381
1382 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1383 and sectors on the device, which are passed directly to sfdisk as
1384 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1385 of these, then the corresponding parameter is omitted.  Usually for
1386 'large' disks, you can just pass C<0> for these, but for small
1387 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1388 out the right geometry and you will need to tell it.
1389
1390 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1391 information refer to the L<sfdisk(8)> manpage.
1392
1393 To create a single partition occupying the whole disk, you would
1394 pass C<lines> as a single element list, when the single element being
1395 the string C<,> (comma).
1396
1397 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1398
1399   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1400    [InitBasicFS, Always, TestOutput (
1401       [["write_file"; "/new"; "new file contents"; "0"];
1402        ["cat"; "/new"]], "new file contents");
1403     InitBasicFS, Always, TestOutput (
1404       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1405        ["cat"; "/new"]], "\nnew file contents\n");
1406     InitBasicFS, Always, TestOutput (
1407       [["write_file"; "/new"; "\n\n"; "0"];
1408        ["cat"; "/new"]], "\n\n");
1409     InitBasicFS, Always, TestOutput (
1410       [["write_file"; "/new"; ""; "0"];
1411        ["cat"; "/new"]], "");
1412     InitBasicFS, Always, TestOutput (
1413       [["write_file"; "/new"; "\n\n\n"; "0"];
1414        ["cat"; "/new"]], "\n\n\n");
1415     InitBasicFS, Always, TestOutput (
1416       [["write_file"; "/new"; "\n"; "0"];
1417        ["cat"; "/new"]], "\n")],
1418    "create a file",
1419    "\
1420 This call creates a file called C<path>.  The contents of the
1421 file is the string C<content> (which can contain any 8 bit data),
1422 with length C<size>.
1423
1424 As a special case, if C<size> is C<0>
1425 then the length is calculated using C<strlen> (so in this case
1426 the content cannot contain embedded ASCII NULs).
1427
1428 I<NB.> Owing to a bug, writing content containing ASCII NUL
1429 characters does I<not> work, even if the length is specified.
1430 We hope to resolve this bug in a future version.  In the meantime
1431 use C<guestfs_upload>.");
1432
1433   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ","];
1436        ["mkfs"; "ext2"; "/dev/sda1"];
1437        ["mount"; "/dev/sda1"; "/"];
1438        ["mounts"]], ["/dev/sda1"]);
1439     InitEmpty, Always, TestOutputList (
1440       [["sfdiskM"; "/dev/sda"; ","];
1441        ["mkfs"; "ext2"; "/dev/sda1"];
1442        ["mount"; "/dev/sda1"; "/"];
1443        ["umount"; "/"];
1444        ["mounts"]], [])],
1445    "unmount a filesystem",
1446    "\
1447 This unmounts the given filesystem.  The filesystem may be
1448 specified either by its mountpoint (path) or the device which
1449 contains the filesystem.");
1450
1451   ("mounts", (RStringList "devices", []), 46, [],
1452    [InitBasicFS, Always, TestOutputListOfDevices (
1453       [["mounts"]], ["/dev/sda1"])],
1454    "show mounted filesystems",
1455    "\
1456 This returns the list of currently mounted filesystems.  It returns
1457 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1458
1459 Some internal mounts are not shown.
1460
1461 See also: C<guestfs_mountpoints>");
1462
1463   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1464    [InitBasicFS, Always, TestOutputList (
1465       [["umount_all"];
1466        ["mounts"]], []);
1467     (* check that umount_all can unmount nested mounts correctly: *)
1468     InitEmpty, Always, TestOutputList (
1469       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1470        ["mkfs"; "ext2"; "/dev/sda1"];
1471        ["mkfs"; "ext2"; "/dev/sda2"];
1472        ["mkfs"; "ext2"; "/dev/sda3"];
1473        ["mount"; "/dev/sda1"; "/"];
1474        ["mkdir"; "/mp1"];
1475        ["mount"; "/dev/sda2"; "/mp1"];
1476        ["mkdir"; "/mp1/mp2"];
1477        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1478        ["mkdir"; "/mp1/mp2/mp3"];
1479        ["umount_all"];
1480        ["mounts"]], [])],
1481    "unmount all filesystems",
1482    "\
1483 This unmounts all mounted filesystems.
1484
1485 Some internal mounts are not unmounted by this call.");
1486
1487   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1488    [],
1489    "remove all LVM LVs, VGs and PVs",
1490    "\
1491 This command removes all LVM logical volumes, volume groups
1492 and physical volumes.");
1493
1494   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1495    [InitSquashFS, Always, TestOutput (
1496       [["file"; "/empty"]], "empty");
1497     InitSquashFS, Always, TestOutput (
1498       [["file"; "/known-1"]], "ASCII text");
1499     InitSquashFS, Always, TestLastFail (
1500       [["file"; "/notexists"]])],
1501    "determine file type",
1502    "\
1503 This call uses the standard L<file(1)> command to determine
1504 the type or contents of the file.  This also works on devices,
1505 for example to find out whether a partition contains a filesystem.
1506
1507 This call will also transparently look inside various types
1508 of compressed file.
1509
1510 The exact command which runs is C<file -zbsL path>.  Note in
1511 particular that the filename is not prepended to the output
1512 (the C<-b> option).");
1513
1514   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1515    [InitBasicFS, Always, TestOutput (
1516       [["upload"; "test-command"; "/test-command"];
1517        ["chmod"; "0o755"; "/test-command"];
1518        ["command"; "/test-command 1"]], "Result1");
1519     InitBasicFS, Always, TestOutput (
1520       [["upload"; "test-command"; "/test-command"];
1521        ["chmod"; "0o755"; "/test-command"];
1522        ["command"; "/test-command 2"]], "Result2\n");
1523     InitBasicFS, Always, TestOutput (
1524       [["upload"; "test-command"; "/test-command"];
1525        ["chmod"; "0o755"; "/test-command"];
1526        ["command"; "/test-command 3"]], "\nResult3");
1527     InitBasicFS, Always, TestOutput (
1528       [["upload"; "test-command"; "/test-command"];
1529        ["chmod"; "0o755"; "/test-command"];
1530        ["command"; "/test-command 4"]], "\nResult4\n");
1531     InitBasicFS, Always, TestOutput (
1532       [["upload"; "test-command"; "/test-command"];
1533        ["chmod"; "0o755"; "/test-command"];
1534        ["command"; "/test-command 5"]], "\nResult5\n\n");
1535     InitBasicFS, Always, TestOutput (
1536       [["upload"; "test-command"; "/test-command"];
1537        ["chmod"; "0o755"; "/test-command"];
1538        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["upload"; "test-command"; "/test-command"];
1541        ["chmod"; "0o755"; "/test-command"];
1542        ["command"; "/test-command 7"]], "");
1543     InitBasicFS, Always, TestOutput (
1544       [["upload"; "test-command"; "/test-command"];
1545        ["chmod"; "0o755"; "/test-command"];
1546        ["command"; "/test-command 8"]], "\n");
1547     InitBasicFS, Always, TestOutput (
1548       [["upload"; "test-command"; "/test-command"];
1549        ["chmod"; "0o755"; "/test-command"];
1550        ["command"; "/test-command 9"]], "\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["upload"; "test-command"; "/test-command"];
1553        ["chmod"; "0o755"; "/test-command"];
1554        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1555     InitBasicFS, Always, TestOutput (
1556       [["upload"; "test-command"; "/test-command"];
1557        ["chmod"; "0o755"; "/test-command"];
1558        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1559     InitBasicFS, Always, TestLastFail (
1560       [["upload"; "test-command"; "/test-command"];
1561        ["chmod"; "0o755"; "/test-command"];
1562        ["command"; "/test-command"]])],
1563    "run a command from the guest filesystem",
1564    "\
1565 This call runs a command from the guest filesystem.  The
1566 filesystem must be mounted, and must contain a compatible
1567 operating system (ie. something Linux, with the same
1568 or compatible processor architecture).
1569
1570 The single parameter is an argv-style list of arguments.
1571 The first element is the name of the program to run.
1572 Subsequent elements are parameters.  The list must be
1573 non-empty (ie. must contain a program name).  Note that
1574 the command runs directly, and is I<not> invoked via
1575 the shell (see C<guestfs_sh>).
1576
1577 The return value is anything printed to I<stdout> by
1578 the command.
1579
1580 If the command returns a non-zero exit status, then
1581 this function returns an error message.  The error message
1582 string is the content of I<stderr> from the command.
1583
1584 The C<$PATH> environment variable will contain at least
1585 C</usr/bin> and C</bin>.  If you require a program from
1586 another location, you should provide the full path in the
1587 first parameter.
1588
1589 Shared libraries and data files required by the program
1590 must be available on filesystems which are mounted in the
1591 correct places.  It is the caller's responsibility to ensure
1592 all filesystems that are needed are mounted at the right
1593 locations.");
1594
1595   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1596    [InitBasicFS, Always, TestOutputList (
1597       [["upload"; "test-command"; "/test-command"];
1598        ["chmod"; "0o755"; "/test-command"];
1599        ["command_lines"; "/test-command 1"]], ["Result1"]);
1600     InitBasicFS, Always, TestOutputList (
1601       [["upload"; "test-command"; "/test-command"];
1602        ["chmod"; "0o755"; "/test-command"];
1603        ["command_lines"; "/test-command 2"]], ["Result2"]);
1604     InitBasicFS, Always, TestOutputList (
1605       [["upload"; "test-command"; "/test-command"];
1606        ["chmod"; "0o755"; "/test-command"];
1607        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1608     InitBasicFS, Always, TestOutputList (
1609       [["upload"; "test-command"; "/test-command"];
1610        ["chmod"; "0o755"; "/test-command"];
1611        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1612     InitBasicFS, Always, TestOutputList (
1613       [["upload"; "test-command"; "/test-command"];
1614        ["chmod"; "0o755"; "/test-command"];
1615        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1616     InitBasicFS, Always, TestOutputList (
1617       [["upload"; "test-command"; "/test-command"];
1618        ["chmod"; "0o755"; "/test-command"];
1619        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1620     InitBasicFS, Always, TestOutputList (
1621       [["upload"; "test-command"; "/test-command"];
1622        ["chmod"; "0o755"; "/test-command"];
1623        ["command_lines"; "/test-command 7"]], []);
1624     InitBasicFS, Always, TestOutputList (
1625       [["upload"; "test-command"; "/test-command"];
1626        ["chmod"; "0o755"; "/test-command"];
1627        ["command_lines"; "/test-command 8"]], [""]);
1628     InitBasicFS, Always, TestOutputList (
1629       [["upload"; "test-command"; "/test-command"];
1630        ["chmod"; "0o755"; "/test-command"];
1631        ["command_lines"; "/test-command 9"]], ["";""]);
1632     InitBasicFS, Always, TestOutputList (
1633       [["upload"; "test-command"; "/test-command"];
1634        ["chmod"; "0o755"; "/test-command"];
1635        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1636     InitBasicFS, Always, TestOutputList (
1637       [["upload"; "test-command"; "/test-command"];
1638        ["chmod"; "0o755"; "/test-command"];
1639        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1640    "run a command, returning lines",
1641    "\
1642 This is the same as C<guestfs_command>, but splits the
1643 result into a list of lines.
1644
1645 See also: C<guestfs_sh_lines>");
1646
1647   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1648    [InitSquashFS, Always, TestOutputStruct (
1649       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1650    "get file information",
1651    "\
1652 Returns file information for the given C<path>.
1653
1654 This is the same as the C<stat(2)> system call.");
1655
1656   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1657    [InitSquashFS, Always, TestOutputStruct (
1658       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1659    "get file information for a symbolic link",
1660    "\
1661 Returns file information for the given C<path>.
1662
1663 This is the same as C<guestfs_stat> except that if C<path>
1664 is a symbolic link, then the link is stat-ed, not the file it
1665 refers to.
1666
1667 This is the same as the C<lstat(2)> system call.");
1668
1669   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1670    [InitSquashFS, Always, TestOutputStruct (
1671       [["statvfs"; "/"]], [CompareWithInt ("namemax", 256)])],
1672    "get file system statistics",
1673    "\
1674 Returns file system statistics for any mounted file system.
1675 C<path> should be a file or directory in the mounted file system
1676 (typically it is the mount point itself, but it doesn't need to be).
1677
1678 This is the same as the C<statvfs(2)> system call.");
1679
1680   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1681    [], (* XXX test *)
1682    "get ext2/ext3/ext4 superblock details",
1683    "\
1684 This returns the contents of the ext2, ext3 or ext4 filesystem
1685 superblock on C<device>.
1686
1687 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1688 manpage for more details.  The list of fields returned isn't
1689 clearly defined, and depends on both the version of C<tune2fs>
1690 that libguestfs was built against, and the filesystem itself.");
1691
1692   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1693    [InitEmpty, Always, TestOutputTrue (
1694       [["blockdev_setro"; "/dev/sda"];
1695        ["blockdev_getro"; "/dev/sda"]])],
1696    "set block device to read-only",
1697    "\
1698 Sets the block device named C<device> to read-only.
1699
1700 This uses the L<blockdev(8)> command.");
1701
1702   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1703    [InitEmpty, Always, TestOutputFalse (
1704       [["blockdev_setrw"; "/dev/sda"];
1705        ["blockdev_getro"; "/dev/sda"]])],
1706    "set block device to read-write",
1707    "\
1708 Sets the block device named C<device> to read-write.
1709
1710 This uses the L<blockdev(8)> command.");
1711
1712   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1713    [InitEmpty, Always, TestOutputTrue (
1714       [["blockdev_setro"; "/dev/sda"];
1715        ["blockdev_getro"; "/dev/sda"]])],
1716    "is block device set to read-only",
1717    "\
1718 Returns a boolean indicating if the block device is read-only
1719 (true if read-only, false if not).
1720
1721 This uses the L<blockdev(8)> command.");
1722
1723   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1724    [InitEmpty, Always, TestOutputInt (
1725       [["blockdev_getss"; "/dev/sda"]], 512)],
1726    "get sectorsize of block device",
1727    "\
1728 This returns the size of sectors on a block device.
1729 Usually 512, but can be larger for modern devices.
1730
1731 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1732 for that).
1733
1734 This uses the L<blockdev(8)> command.");
1735
1736   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1737    [InitEmpty, Always, TestOutputInt (
1738       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1739    "get blocksize of block device",
1740    "\
1741 This returns the block size of a device.
1742
1743 (Note this is different from both I<size in blocks> and
1744 I<filesystem block size>).
1745
1746 This uses the L<blockdev(8)> command.");
1747
1748   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1749    [], (* XXX test *)
1750    "set blocksize of block device",
1751    "\
1752 This sets the block size of a device.
1753
1754 (Note this is different from both I<size in blocks> and
1755 I<filesystem block size>).
1756
1757 This uses the L<blockdev(8)> command.");
1758
1759   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1760    [InitEmpty, Always, TestOutputInt (
1761       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1762    "get total size of device in 512-byte sectors",
1763    "\
1764 This returns the size of the device in units of 512-byte sectors
1765 (even if the sectorsize isn't 512 bytes ... weird).
1766
1767 See also C<guestfs_blockdev_getss> for the real sector size of
1768 the device, and C<guestfs_blockdev_getsize64> for the more
1769 useful I<size in bytes>.
1770
1771 This uses the L<blockdev(8)> command.");
1772
1773   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1774    [InitEmpty, Always, TestOutputInt (
1775       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1776    "get total size of device in bytes",
1777    "\
1778 This returns the size of the device in bytes.
1779
1780 See also C<guestfs_blockdev_getsz>.
1781
1782 This uses the L<blockdev(8)> command.");
1783
1784   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1785    [InitEmpty, Always, TestRun
1786       [["blockdev_flushbufs"; "/dev/sda"]]],
1787    "flush device buffers",
1788    "\
1789 This tells the kernel to flush internal buffers associated
1790 with C<device>.
1791
1792 This uses the L<blockdev(8)> command.");
1793
1794   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1795    [InitEmpty, Always, TestRun
1796       [["blockdev_rereadpt"; "/dev/sda"]]],
1797    "reread partition table",
1798    "\
1799 Reread the partition table on C<device>.
1800
1801 This uses the L<blockdev(8)> command.");
1802
1803   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1804    [InitBasicFS, Always, TestOutput (
1805       (* Pick a file from cwd which isn't likely to change. *)
1806       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1807        ["checksum"; "md5"; "/COPYING.LIB"]],
1808         Digest.to_hex (Digest.file "COPYING.LIB"))],
1809    "upload a file from the local machine",
1810    "\
1811 Upload local file C<filename> to C<remotefilename> on the
1812 filesystem.
1813
1814 C<filename> can also be a named pipe.
1815
1816 See also C<guestfs_download>.");
1817
1818   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1819    [InitBasicFS, Always, TestOutput (
1820       (* Pick a file from cwd which isn't likely to change. *)
1821       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1822        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1823        ["upload"; "testdownload.tmp"; "/upload"];
1824        ["checksum"; "md5"; "/upload"]],
1825         Digest.to_hex (Digest.file "COPYING.LIB"))],
1826    "download a file to the local machine",
1827    "\
1828 Download file C<remotefilename> and save it as C<filename>
1829 on the local machine.
1830
1831 C<filename> can also be a named pipe.
1832
1833 See also C<guestfs_upload>, C<guestfs_cat>.");
1834
1835   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1836    [InitSquashFS, Always, TestOutput (
1837       [["checksum"; "crc"; "/known-3"]], "2891671662");
1838     InitSquashFS, Always, TestLastFail (
1839       [["checksum"; "crc"; "/notexists"]]);
1840     InitSquashFS, Always, TestOutput (
1841       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1842     InitSquashFS, Always, TestOutput (
1843       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1844     InitSquashFS, Always, TestOutput (
1845       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1846     InitSquashFS, Always, TestOutput (
1847       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1848     InitSquashFS, Always, TestOutput (
1849       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1850     InitSquashFS, Always, TestOutput (
1851       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1852    "compute MD5, SHAx or CRC checksum of file",
1853    "\
1854 This call computes the MD5, SHAx or CRC checksum of the
1855 file named C<path>.
1856
1857 The type of checksum to compute is given by the C<csumtype>
1858 parameter which must have one of the following values:
1859
1860 =over 4
1861
1862 =item C<crc>
1863
1864 Compute the cyclic redundancy check (CRC) specified by POSIX
1865 for the C<cksum> command.
1866
1867 =item C<md5>
1868
1869 Compute the MD5 hash (using the C<md5sum> program).
1870
1871 =item C<sha1>
1872
1873 Compute the SHA1 hash (using the C<sha1sum> program).
1874
1875 =item C<sha224>
1876
1877 Compute the SHA224 hash (using the C<sha224sum> program).
1878
1879 =item C<sha256>
1880
1881 Compute the SHA256 hash (using the C<sha256sum> program).
1882
1883 =item C<sha384>
1884
1885 Compute the SHA384 hash (using the C<sha384sum> program).
1886
1887 =item C<sha512>
1888
1889 Compute the SHA512 hash (using the C<sha512sum> program).
1890
1891 =back
1892
1893 The checksum is returned as a printable string.");
1894
1895   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1896    [InitBasicFS, Always, TestOutput (
1897       [["tar_in"; "../images/helloworld.tar"; "/"];
1898        ["cat"; "/hello"]], "hello\n")],
1899    "unpack tarfile to directory",
1900    "\
1901 This command uploads and unpacks local file C<tarfile> (an
1902 I<uncompressed> tar file) into C<directory>.
1903
1904 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1905
1906   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1907    [],
1908    "pack directory into tarfile",
1909    "\
1910 This command packs the contents of C<directory> and downloads
1911 it to local file C<tarfile>.
1912
1913 To download a compressed tarball, use C<guestfs_tgz_out>.");
1914
1915   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1916    [InitBasicFS, Always, TestOutput (
1917       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1918        ["cat"; "/hello"]], "hello\n")],
1919    "unpack compressed tarball to directory",
1920    "\
1921 This command uploads and unpacks local file C<tarball> (a
1922 I<gzip compressed> tar file) into C<directory>.
1923
1924 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1925
1926   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1927    [],
1928    "pack directory into compressed tarball",
1929    "\
1930 This command packs the contents of C<directory> and downloads
1931 it to local file C<tarball>.
1932
1933 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1934
1935   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1936    [InitBasicFS, Always, TestLastFail (
1937       [["umount"; "/"];
1938        ["mount_ro"; "/dev/sda1"; "/"];
1939        ["touch"; "/new"]]);
1940     InitBasicFS, Always, TestOutput (
1941       [["write_file"; "/new"; "data"; "0"];
1942        ["umount"; "/"];
1943        ["mount_ro"; "/dev/sda1"; "/"];
1944        ["cat"; "/new"]], "data")],
1945    "mount a guest disk, read-only",
1946    "\
1947 This is the same as the C<guestfs_mount> command, but it
1948 mounts the filesystem with the read-only (I<-o ro>) flag.");
1949
1950   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1951    [],
1952    "mount a guest disk with mount options",
1953    "\
1954 This is the same as the C<guestfs_mount> command, but it
1955 allows you to set the mount options as for the
1956 L<mount(8)> I<-o> flag.");
1957
1958   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1959    [],
1960    "mount a guest disk with mount options and vfstype",
1961    "\
1962 This is the same as the C<guestfs_mount> command, but it
1963 allows you to set both the mount options and the vfstype
1964 as for the L<mount(8)> I<-o> and I<-t> flags.");
1965
1966   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1967    [],
1968    "debugging and internals",
1969    "\
1970 The C<guestfs_debug> command exposes some internals of
1971 C<guestfsd> (the guestfs daemon) that runs inside the
1972 qemu subprocess.
1973
1974 There is no comprehensive help for this command.  You have
1975 to look at the file C<daemon/debug.c> in the libguestfs source
1976 to find out what you can do.");
1977
1978   ("lvremove", (RErr, [Device "device"]), 77, [],
1979    [InitEmpty, Always, TestOutputList (
1980       [["sfdiskM"; "/dev/sda"; ","];
1981        ["pvcreate"; "/dev/sda1"];
1982        ["vgcreate"; "VG"; "/dev/sda1"];
1983        ["lvcreate"; "LV1"; "VG"; "50"];
1984        ["lvcreate"; "LV2"; "VG"; "50"];
1985        ["lvremove"; "/dev/VG/LV1"];
1986        ["lvs"]], ["/dev/VG/LV2"]);
1987     InitEmpty, Always, TestOutputList (
1988       [["sfdiskM"; "/dev/sda"; ","];
1989        ["pvcreate"; "/dev/sda1"];
1990        ["vgcreate"; "VG"; "/dev/sda1"];
1991        ["lvcreate"; "LV1"; "VG"; "50"];
1992        ["lvcreate"; "LV2"; "VG"; "50"];
1993        ["lvremove"; "/dev/VG"];
1994        ["lvs"]], []);
1995     InitEmpty, Always, TestOutputList (
1996       [["sfdiskM"; "/dev/sda"; ","];
1997        ["pvcreate"; "/dev/sda1"];
1998        ["vgcreate"; "VG"; "/dev/sda1"];
1999        ["lvcreate"; "LV1"; "VG"; "50"];
2000        ["lvcreate"; "LV2"; "VG"; "50"];
2001        ["lvremove"; "/dev/VG"];
2002        ["vgs"]], ["VG"])],
2003    "remove an LVM logical volume",
2004    "\
2005 Remove an LVM logical volume C<device>, where C<device> is
2006 the path to the LV, such as C</dev/VG/LV>.
2007
2008 You can also remove all LVs in a volume group by specifying
2009 the VG name, C</dev/VG>.");
2010
2011   ("vgremove", (RErr, [String "vgname"]), 78, [],
2012    [InitEmpty, Always, TestOutputList (
2013       [["sfdiskM"; "/dev/sda"; ","];
2014        ["pvcreate"; "/dev/sda1"];
2015        ["vgcreate"; "VG"; "/dev/sda1"];
2016        ["lvcreate"; "LV1"; "VG"; "50"];
2017        ["lvcreate"; "LV2"; "VG"; "50"];
2018        ["vgremove"; "VG"];
2019        ["lvs"]], []);
2020     InitEmpty, Always, TestOutputList (
2021       [["sfdiskM"; "/dev/sda"; ","];
2022        ["pvcreate"; "/dev/sda1"];
2023        ["vgcreate"; "VG"; "/dev/sda1"];
2024        ["lvcreate"; "LV1"; "VG"; "50"];
2025        ["lvcreate"; "LV2"; "VG"; "50"];
2026        ["vgremove"; "VG"];
2027        ["vgs"]], [])],
2028    "remove an LVM volume group",
2029    "\
2030 Remove an LVM volume group C<vgname>, (for example C<VG>).
2031
2032 This also forcibly removes all logical volumes in the volume
2033 group (if any).");
2034
2035   ("pvremove", (RErr, [Device "device"]), 79, [],
2036    [InitEmpty, Always, TestOutputListOfDevices (
2037       [["sfdiskM"; "/dev/sda"; ","];
2038        ["pvcreate"; "/dev/sda1"];
2039        ["vgcreate"; "VG"; "/dev/sda1"];
2040        ["lvcreate"; "LV1"; "VG"; "50"];
2041        ["lvcreate"; "LV2"; "VG"; "50"];
2042        ["vgremove"; "VG"];
2043        ["pvremove"; "/dev/sda1"];
2044        ["lvs"]], []);
2045     InitEmpty, Always, TestOutputListOfDevices (
2046       [["sfdiskM"; "/dev/sda"; ","];
2047        ["pvcreate"; "/dev/sda1"];
2048        ["vgcreate"; "VG"; "/dev/sda1"];
2049        ["lvcreate"; "LV1"; "VG"; "50"];
2050        ["lvcreate"; "LV2"; "VG"; "50"];
2051        ["vgremove"; "VG"];
2052        ["pvremove"; "/dev/sda1"];
2053        ["vgs"]], []);
2054     InitEmpty, Always, TestOutputListOfDevices (
2055       [["sfdiskM"; "/dev/sda"; ","];
2056        ["pvcreate"; "/dev/sda1"];
2057        ["vgcreate"; "VG"; "/dev/sda1"];
2058        ["lvcreate"; "LV1"; "VG"; "50"];
2059        ["lvcreate"; "LV2"; "VG"; "50"];
2060        ["vgremove"; "VG"];
2061        ["pvremove"; "/dev/sda1"];
2062        ["pvs"]], [])],
2063    "remove an LVM physical volume",
2064    "\
2065 This wipes a physical volume C<device> so that LVM will no longer
2066 recognise it.
2067
2068 The implementation uses the C<pvremove> command which refuses to
2069 wipe physical volumes that contain any volume groups, so you have
2070 to remove those first.");
2071
2072   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2073    [InitBasicFS, Always, TestOutput (
2074       [["set_e2label"; "/dev/sda1"; "testlabel"];
2075        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2076    "set the ext2/3/4 filesystem label",
2077    "\
2078 This sets the ext2/3/4 filesystem label of the filesystem on
2079 C<device> to C<label>.  Filesystem labels are limited to
2080 16 characters.
2081
2082 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2083 to return the existing label on a filesystem.");
2084
2085   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2086    [],
2087    "get the ext2/3/4 filesystem label",
2088    "\
2089 This returns the ext2/3/4 filesystem label of the filesystem on
2090 C<device>.");
2091
2092   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2093    (let uuid = uuidgen () in
2094     [InitBasicFS, Always, TestOutput (
2095        [["set_e2uuid"; "/dev/sda1"; uuid];
2096         ["get_e2uuid"; "/dev/sda1"]], uuid);
2097      InitBasicFS, Always, TestOutput (
2098        [["set_e2uuid"; "/dev/sda1"; "clear"];
2099         ["get_e2uuid"; "/dev/sda1"]], "");
2100      (* We can't predict what UUIDs will be, so just check the commands run. *)
2101      InitBasicFS, Always, TestRun (
2102        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2103      InitBasicFS, Always, TestRun (
2104        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2105    "set the ext2/3/4 filesystem UUID",
2106    "\
2107 This sets the ext2/3/4 filesystem UUID of the filesystem on
2108 C<device> to C<uuid>.  The format of the UUID and alternatives
2109 such as C<clear>, C<random> and C<time> are described in the
2110 L<tune2fs(8)> manpage.
2111
2112 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2113 to return the existing UUID of a filesystem.");
2114
2115   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2116    [],
2117    "get the ext2/3/4 filesystem UUID",
2118    "\
2119 This returns the ext2/3/4 filesystem UUID of the filesystem on
2120 C<device>.");
2121
2122   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2123    [InitBasicFS, Always, TestOutputInt (
2124       [["umount"; "/dev/sda1"];
2125        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2126     InitBasicFS, Always, TestOutputInt (
2127       [["umount"; "/dev/sda1"];
2128        ["zero"; "/dev/sda1"];
2129        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2130    "run the filesystem checker",
2131    "\
2132 This runs the filesystem checker (fsck) on C<device> which
2133 should have filesystem type C<fstype>.
2134
2135 The returned integer is the status.  See L<fsck(8)> for the
2136 list of status codes from C<fsck>.
2137
2138 Notes:
2139
2140 =over 4
2141
2142 =item *
2143
2144 Multiple status codes can be summed together.
2145
2146 =item *
2147
2148 A non-zero return code can mean \"success\", for example if
2149 errors have been corrected on the filesystem.
2150
2151 =item *
2152
2153 Checking or repairing NTFS volumes is not supported
2154 (by linux-ntfs).
2155
2156 =back
2157
2158 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2159
2160   ("zero", (RErr, [Device "device"]), 85, [],
2161    [InitBasicFS, Always, TestOutput (
2162       [["umount"; "/dev/sda1"];
2163        ["zero"; "/dev/sda1"];
2164        ["file"; "/dev/sda1"]], "data")],
2165    "write zeroes to the device",
2166    "\
2167 This command writes zeroes over the first few blocks of C<device>.
2168
2169 How many blocks are zeroed isn't specified (but it's I<not> enough
2170 to securely wipe the device).  It should be sufficient to remove
2171 any partition tables, filesystem superblocks and so on.
2172
2173 See also: C<guestfs_scrub_device>.");
2174
2175   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2176    (* Test disabled because grub-install incompatible with virtio-blk driver.
2177     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2178     *)
2179    [InitBasicFS, Disabled, TestOutputTrue (
2180       [["grub_install"; "/"; "/dev/sda1"];
2181        ["is_dir"; "/boot"]])],
2182    "install GRUB",
2183    "\
2184 This command installs GRUB (the Grand Unified Bootloader) on
2185 C<device>, with the root directory being C<root>.");
2186
2187   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2188    [InitBasicFS, Always, TestOutput (
2189       [["write_file"; "/old"; "file content"; "0"];
2190        ["cp"; "/old"; "/new"];
2191        ["cat"; "/new"]], "file content");
2192     InitBasicFS, Always, TestOutputTrue (
2193       [["write_file"; "/old"; "file content"; "0"];
2194        ["cp"; "/old"; "/new"];
2195        ["is_file"; "/old"]]);
2196     InitBasicFS, Always, TestOutput (
2197       [["write_file"; "/old"; "file content"; "0"];
2198        ["mkdir"; "/dir"];
2199        ["cp"; "/old"; "/dir/new"];
2200        ["cat"; "/dir/new"]], "file content")],
2201    "copy a file",
2202    "\
2203 This copies a file from C<src> to C<dest> where C<dest> is
2204 either a destination filename or destination directory.");
2205
2206   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2207    [InitBasicFS, Always, TestOutput (
2208       [["mkdir"; "/olddir"];
2209        ["mkdir"; "/newdir"];
2210        ["write_file"; "/olddir/file"; "file content"; "0"];
2211        ["cp_a"; "/olddir"; "/newdir"];
2212        ["cat"; "/newdir/olddir/file"]], "file content")],
2213    "copy a file or directory recursively",
2214    "\
2215 This copies a file or directory from C<src> to C<dest>
2216 recursively using the C<cp -a> command.");
2217
2218   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2219    [InitBasicFS, Always, TestOutput (
2220       [["write_file"; "/old"; "file content"; "0"];
2221        ["mv"; "/old"; "/new"];
2222        ["cat"; "/new"]], "file content");
2223     InitBasicFS, Always, TestOutputFalse (
2224       [["write_file"; "/old"; "file content"; "0"];
2225        ["mv"; "/old"; "/new"];
2226        ["is_file"; "/old"]])],
2227    "move a file",
2228    "\
2229 This moves a file from C<src> to C<dest> where C<dest> is
2230 either a destination filename or destination directory.");
2231
2232   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2233    [InitEmpty, Always, TestRun (
2234       [["drop_caches"; "3"]])],
2235    "drop kernel page cache, dentries and inodes",
2236    "\
2237 This instructs the guest kernel to drop its page cache,
2238 and/or dentries and inode caches.  The parameter C<whattodrop>
2239 tells the kernel what precisely to drop, see
2240 L<http://linux-mm.org/Drop_Caches>
2241
2242 Setting C<whattodrop> to 3 should drop everything.
2243
2244 This automatically calls L<sync(2)> before the operation,
2245 so that the maximum guest memory is freed.");
2246
2247   ("dmesg", (RString "kmsgs", []), 91, [],
2248    [InitEmpty, Always, TestRun (
2249       [["dmesg"]])],
2250    "return kernel messages",
2251    "\
2252 This returns the kernel messages (C<dmesg> output) from
2253 the guest kernel.  This is sometimes useful for extended
2254 debugging of problems.
2255
2256 Another way to get the same information is to enable
2257 verbose messages with C<guestfs_set_verbose> or by setting
2258 the environment variable C<LIBGUESTFS_DEBUG=1> before
2259 running the program.");
2260
2261   ("ping_daemon", (RErr, []), 92, [],
2262    [InitEmpty, Always, TestRun (
2263       [["ping_daemon"]])],
2264    "ping the guest daemon",
2265    "\
2266 This is a test probe into the guestfs daemon running inside
2267 the qemu subprocess.  Calling this function checks that the
2268 daemon responds to the ping message, without affecting the daemon
2269 or attached block device(s) in any other way.");
2270
2271   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2272    [InitBasicFS, Always, TestOutputTrue (
2273       [["write_file"; "/file1"; "contents of a file"; "0"];
2274        ["cp"; "/file1"; "/file2"];
2275        ["equal"; "/file1"; "/file2"]]);
2276     InitBasicFS, Always, TestOutputFalse (
2277       [["write_file"; "/file1"; "contents of a file"; "0"];
2278        ["write_file"; "/file2"; "contents of another file"; "0"];
2279        ["equal"; "/file1"; "/file2"]]);
2280     InitBasicFS, Always, TestLastFail (
2281       [["equal"; "/file1"; "/file2"]])],
2282    "test if two files have equal contents",
2283    "\
2284 This compares the two files C<file1> and C<file2> and returns
2285 true if their content is exactly equal, or false otherwise.
2286
2287 The external L<cmp(1)> program is used for the comparison.");
2288
2289   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2290    [InitSquashFS, Always, TestOutputList (
2291       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2292     InitSquashFS, Always, TestOutputList (
2293       [["strings"; "/empty"]], [])],
2294    "print the printable strings in a file",
2295    "\
2296 This runs the L<strings(1)> command on a file and returns
2297 the list of printable strings found.");
2298
2299   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2300    [InitSquashFS, Always, TestOutputList (
2301       [["strings_e"; "b"; "/known-5"]], []);
2302     InitBasicFS, Disabled, TestOutputList (
2303       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2304        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2305    "print the printable strings in a file",
2306    "\
2307 This is like the C<guestfs_strings> command, but allows you to
2308 specify the encoding.
2309
2310 See the L<strings(1)> manpage for the full list of encodings.
2311
2312 Commonly useful encodings are C<l> (lower case L) which will
2313 show strings inside Windows/x86 files.
2314
2315 The returned strings are transcoded to UTF-8.");
2316
2317   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2318    [InitSquashFS, Always, TestOutput (
2319       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2320     (* Test for RHBZ#501888c2 regression which caused large hexdump
2321      * commands to segfault.
2322      *)
2323     InitSquashFS, Always, TestRun (
2324       [["hexdump"; "/100krandom"]])],
2325    "dump a file in hexadecimal",
2326    "\
2327 This runs C<hexdump -C> on the given C<path>.  The result is
2328 the human-readable, canonical hex dump of the file.");
2329
2330   ("zerofree", (RErr, [Device "device"]), 97, [],
2331    [InitNone, Always, TestOutput (
2332       [["sfdiskM"; "/dev/sda"; ","];
2333        ["mkfs"; "ext3"; "/dev/sda1"];
2334        ["mount"; "/dev/sda1"; "/"];
2335        ["write_file"; "/new"; "test file"; "0"];
2336        ["umount"; "/dev/sda1"];
2337        ["zerofree"; "/dev/sda1"];
2338        ["mount"; "/dev/sda1"; "/"];
2339        ["cat"; "/new"]], "test file")],
2340    "zero unused inodes and disk blocks on ext2/3 filesystem",
2341    "\
2342 This runs the I<zerofree> program on C<device>.  This program
2343 claims to zero unused inodes and disk blocks on an ext2/3
2344 filesystem, thus making it possible to compress the filesystem
2345 more effectively.
2346
2347 You should B<not> run this program if the filesystem is
2348 mounted.
2349
2350 It is possible that using this program can damage the filesystem
2351 or data on the filesystem.");
2352
2353   ("pvresize", (RErr, [Device "device"]), 98, [],
2354    [],
2355    "resize an LVM physical volume",
2356    "\
2357 This resizes (expands or shrinks) an existing LVM physical
2358 volume to match the new size of the underlying device.");
2359
2360   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2361                        Int "cyls"; Int "heads"; Int "sectors";
2362                        String "line"]), 99, [DangerWillRobinson],
2363    [],
2364    "modify a single partition on a block device",
2365    "\
2366 This runs L<sfdisk(8)> option to modify just the single
2367 partition C<n> (note: C<n> counts from 1).
2368
2369 For other parameters, see C<guestfs_sfdisk>.  You should usually
2370 pass C<0> for the cyls/heads/sectors parameters.");
2371
2372   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2373    [],
2374    "display the partition table",
2375    "\
2376 This displays the partition table on C<device>, in the
2377 human-readable output of the L<sfdisk(8)> command.  It is
2378 not intended to be parsed.");
2379
2380   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2381    [],
2382    "display the kernel geometry",
2383    "\
2384 This displays the kernel's idea of the geometry of C<device>.
2385
2386 The result is in human-readable format, and not designed to
2387 be parsed.");
2388
2389   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2390    [],
2391    "display the disk geometry from the partition table",
2392    "\
2393 This displays the disk geometry of C<device> read from the
2394 partition table.  Especially in the case where the underlying
2395 block device has been resized, this can be different from the
2396 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2397
2398 The result is in human-readable format, and not designed to
2399 be parsed.");
2400
2401   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2402    [],
2403    "activate or deactivate all volume groups",
2404    "\
2405 This command activates or (if C<activate> is false) deactivates
2406 all logical volumes in all volume groups.
2407 If activated, then they are made known to the
2408 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2409 then those devices disappear.
2410
2411 This command is the same as running C<vgchange -a y|n>");
2412
2413   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2414    [],
2415    "activate or deactivate some volume groups",
2416    "\
2417 This command activates or (if C<activate> is false) deactivates
2418 all logical volumes in the listed volume groups C<volgroups>.
2419 If activated, then they are made known to the
2420 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2421 then those devices disappear.
2422
2423 This command is the same as running C<vgchange -a y|n volgroups...>
2424
2425 Note that if C<volgroups> is an empty list then B<all> volume groups
2426 are activated or deactivated.");
2427
2428   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2429    [InitNone, Always, TestOutput (
2430       [["sfdiskM"; "/dev/sda"; ","];
2431        ["pvcreate"; "/dev/sda1"];
2432        ["vgcreate"; "VG"; "/dev/sda1"];
2433        ["lvcreate"; "LV"; "VG"; "10"];
2434        ["mkfs"; "ext2"; "/dev/VG/LV"];
2435        ["mount"; "/dev/VG/LV"; "/"];
2436        ["write_file"; "/new"; "test content"; "0"];
2437        ["umount"; "/"];
2438        ["lvresize"; "/dev/VG/LV"; "20"];
2439        ["e2fsck_f"; "/dev/VG/LV"];
2440        ["resize2fs"; "/dev/VG/LV"];
2441        ["mount"; "/dev/VG/LV"; "/"];
2442        ["cat"; "/new"]], "test content")],
2443    "resize an LVM logical volume",
2444    "\
2445 This resizes (expands or shrinks) an existing LVM logical
2446 volume to C<mbytes>.  When reducing, data in the reduced part
2447 is lost.");
2448
2449   ("resize2fs", (RErr, [Device "device"]), 106, [],
2450    [], (* lvresize tests this *)
2451    "resize an ext2/ext3 filesystem",
2452    "\
2453 This resizes an ext2 or ext3 filesystem to match the size of
2454 the underlying device.
2455
2456 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2457 on the C<device> before calling this command.  For unknown reasons
2458 C<resize2fs> sometimes gives an error about this and sometimes not.
2459 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2460 calling this function.");
2461
2462   ("find", (RStringList "names", [Pathname "directory"]), 107, [],
2463    [InitBasicFS, Always, TestOutputList (
2464       [["find"; "/"]], ["lost+found"]);
2465     InitBasicFS, Always, TestOutputList (
2466       [["touch"; "/a"];
2467        ["mkdir"; "/b"];
2468        ["touch"; "/b/c"];
2469        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2470     InitBasicFS, Always, TestOutputList (
2471       [["mkdir_p"; "/a/b/c"];
2472        ["touch"; "/a/b/c/d"];
2473        ["find"; "/a/b/"]], ["c"; "c/d"])],
2474    "find all files and directories",
2475    "\
2476 This command lists out all files and directories, recursively,
2477 starting at C<directory>.  It is essentially equivalent to
2478 running the shell command C<find directory -print> but some
2479 post-processing happens on the output, described below.
2480
2481 This returns a list of strings I<without any prefix>.  Thus
2482 if the directory structure was:
2483
2484  /tmp/a
2485  /tmp/b
2486  /tmp/c/d
2487
2488 then the returned list from C<guestfs_find> C</tmp> would be
2489 4 elements:
2490
2491  a
2492  b
2493  c
2494  c/d
2495
2496 If C<directory> is not a directory, then this command returns
2497 an error.
2498
2499 The returned list is sorted.");
2500
2501   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2502    [], (* lvresize tests this *)
2503    "check an ext2/ext3 filesystem",
2504    "\
2505 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2506 filesystem checker on C<device>, noninteractively (C<-p>),
2507 even if the filesystem appears to be clean (C<-f>).
2508
2509 This command is only needed because of C<guestfs_resize2fs>
2510 (q.v.).  Normally you should use C<guestfs_fsck>.");
2511
2512   ("sleep", (RErr, [Int "secs"]), 109, [],
2513    [InitNone, Always, TestRun (
2514       [["sleep"; "1"]])],
2515    "sleep for some seconds",
2516    "\
2517 Sleep for C<secs> seconds.");
2518
2519   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2520    [InitNone, Always, TestOutputInt (
2521       [["sfdiskM"; "/dev/sda"; ","];
2522        ["mkfs"; "ntfs"; "/dev/sda1"];
2523        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2524     InitNone, Always, TestOutputInt (
2525       [["sfdiskM"; "/dev/sda"; ","];
2526        ["mkfs"; "ext2"; "/dev/sda1"];
2527        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2528    "probe NTFS volume",
2529    "\
2530 This command runs the L<ntfs-3g.probe(8)> command which probes
2531 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2532 be mounted read-write, and some cannot be mounted at all).
2533
2534 C<rw> is a boolean flag.  Set it to true if you want to test
2535 if the volume can be mounted read-write.  Set it to false if
2536 you want to test if the volume can be mounted read-only.
2537
2538 The return value is an integer which C<0> if the operation
2539 would succeed, or some non-zero value documented in the
2540 L<ntfs-3g.probe(8)> manual page.");
2541
2542   ("sh", (RString "output", [String "command"]), 111, [],
2543    [], (* XXX needs tests *)
2544    "run a command via the shell",
2545    "\
2546 This call runs a command from the guest filesystem via the
2547 guest's C</bin/sh>.
2548
2549 This is like C<guestfs_command>, but passes the command to:
2550
2551  /bin/sh -c \"command\"
2552
2553 Depending on the guest's shell, this usually results in
2554 wildcards being expanded, shell expressions being interpolated
2555 and so on.
2556
2557 All the provisos about C<guestfs_command> apply to this call.");
2558
2559   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2560    [], (* XXX needs tests *)
2561    "run a command via the shell returning lines",
2562    "\
2563 This is the same as C<guestfs_sh>, but splits the result
2564 into a list of lines.
2565
2566 See also: C<guestfs_command_lines>");
2567
2568   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2569    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2570     * code in stubs.c, since all valid glob patterns must start with "/".
2571     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2572     *)
2573    [InitBasicFS, Always, TestOutputList (
2574       [["mkdir_p"; "/a/b/c"];
2575        ["touch"; "/a/b/c/d"];
2576        ["touch"; "/a/b/c/e"];
2577        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2578     InitBasicFS, Always, TestOutputList (
2579       [["mkdir_p"; "/a/b/c"];
2580        ["touch"; "/a/b/c/d"];
2581        ["touch"; "/a/b/c/e"];
2582        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2583     InitBasicFS, Always, TestOutputList (
2584       [["mkdir_p"; "/a/b/c"];
2585        ["touch"; "/a/b/c/d"];
2586        ["touch"; "/a/b/c/e"];
2587        ["glob_expand"; "/a/*/x/*"]], [])],
2588    "expand a wildcard path",
2589    "\
2590 This command searches for all the pathnames matching
2591 C<pattern> according to the wildcard expansion rules
2592 used by the shell.
2593
2594 If no paths match, then this returns an empty list
2595 (note: not an error).
2596
2597 It is just a wrapper around the C L<glob(3)> function
2598 with flags C<GLOB_MARK|GLOB_BRACE>.
2599 See that manual page for more details.");
2600
2601   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2602    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2603       [["scrub_device"; "/dev/sdc"]])],
2604    "scrub (securely wipe) a device",
2605    "\
2606 This command writes patterns over C<device> to make data retrieval
2607 more difficult.
2608
2609 It is an interface to the L<scrub(1)> program.  See that
2610 manual page for more details.");
2611
2612   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2613    [InitBasicFS, Always, TestRun (
2614       [["write_file"; "/file"; "content"; "0"];
2615        ["scrub_file"; "/file"]])],
2616    "scrub (securely wipe) a file",
2617    "\
2618 This command writes patterns over a file to make data retrieval
2619 more difficult.
2620
2621 The file is I<removed> after scrubbing.
2622
2623 It is an interface to the L<scrub(1)> program.  See that
2624 manual page for more details.");
2625
2626   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2627    [], (* XXX needs testing *)
2628    "scrub (securely wipe) free space",
2629    "\
2630 This command creates the directory C<dir> and then fills it
2631 with files until the filesystem is full, and scrubs the files
2632 as for C<guestfs_scrub_file>, and deletes them.
2633 The intention is to scrub any free space on the partition
2634 containing C<dir>.
2635
2636 It is an interface to the L<scrub(1)> program.  See that
2637 manual page for more details.");
2638
2639   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2640    [InitBasicFS, Always, TestRun (
2641       [["mkdir"; "/tmp"];
2642        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2643    "create a temporary directory",
2644    "\
2645 This command creates a temporary directory.  The
2646 C<template> parameter should be a full pathname for the
2647 temporary directory name with the final six characters being
2648 \"XXXXXX\".
2649
2650 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2651 the second one being suitable for Windows filesystems.
2652
2653 The name of the temporary directory that was created
2654 is returned.
2655
2656 The temporary directory is created with mode 0700
2657 and is owned by root.
2658
2659 The caller is responsible for deleting the temporary
2660 directory and its contents after use.
2661
2662 See also: L<mkdtemp(3)>");
2663
2664   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2665    [InitSquashFS, Always, TestOutputInt (
2666       [["wc_l"; "/10klines"]], 10000)],
2667    "count lines in a file",
2668    "\
2669 This command counts the lines in a file, using the
2670 C<wc -l> external command.");
2671
2672   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2673    [InitSquashFS, Always, TestOutputInt (
2674       [["wc_w"; "/10klines"]], 10000)],
2675    "count words in a file",
2676    "\
2677 This command counts the words in a file, using the
2678 C<wc -w> external command.");
2679
2680   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2681    [InitSquashFS, Always, TestOutputInt (
2682       [["wc_c"; "/100kallspaces"]], 102400)],
2683    "count characters in a file",
2684    "\
2685 This command counts the characters in a file, using the
2686 C<wc -c> external command.");
2687
2688   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2689    [InitSquashFS, Always, TestOutputList (
2690       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2691    "return first 10 lines of a file",
2692    "\
2693 This command returns up to the first 10 lines of a file as
2694 a list of strings.");
2695
2696   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2697    [InitSquashFS, Always, TestOutputList (
2698       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2699     InitSquashFS, Always, TestOutputList (
2700       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2701     InitSquashFS, Always, TestOutputList (
2702       [["head_n"; "0"; "/10klines"]], [])],
2703    "return first N lines of a file",
2704    "\
2705 If the parameter C<nrlines> is a positive number, this returns the first
2706 C<nrlines> lines of the file C<path>.
2707
2708 If the parameter C<nrlines> is a negative number, this returns lines
2709 from the file C<path>, excluding the last C<nrlines> lines.
2710
2711 If the parameter C<nrlines> is zero, this returns an empty list.");
2712
2713   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2714    [InitSquashFS, Always, TestOutputList (
2715       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2716    "return last 10 lines of a file",
2717    "\
2718 This command returns up to the last 10 lines of a file as
2719 a list of strings.");
2720
2721   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2722    [InitSquashFS, Always, TestOutputList (
2723       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2724     InitSquashFS, Always, TestOutputList (
2725       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2726     InitSquashFS, Always, TestOutputList (
2727       [["tail_n"; "0"; "/10klines"]], [])],
2728    "return last N lines of a file",
2729    "\
2730 If the parameter C<nrlines> is a positive number, this returns the last
2731 C<nrlines> lines of the file C<path>.
2732
2733 If the parameter C<nrlines> is a negative number, this returns lines
2734 from the file C<path>, starting with the C<-nrlines>th line.
2735
2736 If the parameter C<nrlines> is zero, this returns an empty list.");
2737
2738   ("df", (RString "output", []), 125, [],
2739    [], (* XXX Tricky to test because it depends on the exact format
2740         * of the 'df' command and other imponderables.
2741         *)
2742    "report file system disk space usage",
2743    "\
2744 This command runs the C<df> command to report disk space used.
2745
2746 This command is mostly useful for interactive sessions.  It
2747 is I<not> intended that you try to parse the output string.
2748 Use C<statvfs> from programs.");
2749
2750   ("df_h", (RString "output", []), 126, [],
2751    [], (* XXX Tricky to test because it depends on the exact format
2752         * of the 'df' command and other imponderables.
2753         *)
2754    "report file system disk space usage (human readable)",
2755    "\
2756 This command runs the C<df -h> command to report disk space used
2757 in human-readable format.
2758
2759 This command is mostly useful for interactive sessions.  It
2760 is I<not> intended that you try to parse the output string.
2761 Use C<statvfs> from programs.");
2762
2763   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2764    [InitSquashFS, Always, TestOutputInt (
2765       [["du"; "/directory"]], 0 (* squashfs doesn't have blocks *))],
2766    "estimate file space usage",
2767    "\
2768 This command runs the C<du -s> command to estimate file space
2769 usage for C<path>.
2770
2771 C<path> can be a file or a directory.  If C<path> is a directory
2772 then the estimate includes the contents of the directory and all
2773 subdirectories (recursively).
2774
2775 The result is the estimated size in I<kilobytes>
2776 (ie. units of 1024 bytes).");
2777
2778   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2779    [InitSquashFS, Always, TestOutputList (
2780       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2781    "list files in an initrd",
2782    "\
2783 This command lists out files contained in an initrd.
2784
2785 The files are listed without any initial C</> character.  The
2786 files are listed in the order they appear (not necessarily
2787 alphabetical).  Directory names are listed as separate items.
2788
2789 Old Linux kernels (2.4 and earlier) used a compressed ext2
2790 filesystem as initrd.  We I<only> support the newer initramfs
2791 format (compressed cpio files).");
2792
2793   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2794    [],
2795    "mount a file using the loop device",
2796    "\
2797 This command lets you mount C<file> (a filesystem image
2798 in a file) on a mount point.  It is entirely equivalent to
2799 the command C<mount -o loop file mountpoint>.");
2800
2801   ("mkswap", (RErr, [Device "device"]), 130, [],
2802    [InitEmpty, Always, TestRun (
2803       [["sfdiskM"; "/dev/sda"; ","];
2804        ["mkswap"; "/dev/sda1"]])],
2805    "create a swap partition",
2806    "\
2807 Create a swap partition on C<device>.");
2808
2809   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2810    [InitEmpty, Always, TestRun (
2811       [["sfdiskM"; "/dev/sda"; ","];
2812        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2813    "create a swap partition with a label",
2814    "\
2815 Create a swap partition on C<device> with label C<label>.
2816
2817 Note that you cannot attach a swap label to a block device
2818 (eg. C</dev/sda>), just to a partition.  This appears to be
2819 a limitation of the kernel or swap tools.");
2820
2821   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2822    (let uuid = uuidgen () in
2823     [InitEmpty, Always, TestRun (
2824        [["sfdiskM"; "/dev/sda"; ","];
2825         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2826    "create a swap partition with an explicit UUID",
2827    "\
2828 Create a swap partition on C<device> with UUID C<uuid>.");
2829
2830   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2831    [InitBasicFS, Always, TestOutputStruct (
2832       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2833        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2834        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2835     InitBasicFS, Always, TestOutputStruct (
2836       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2837        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2838    "make block, character or FIFO devices",
2839    "\
2840 This call creates block or character special devices, or
2841 named pipes (FIFOs).
2842
2843 The C<mode> parameter should be the mode, using the standard
2844 constants.  C<devmajor> and C<devminor> are the
2845 device major and minor numbers, only used when creating block
2846 and character special devices.");
2847
2848   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2849    [InitBasicFS, Always, TestOutputStruct (
2850       [["mkfifo"; "0o777"; "/node"];
2851        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2852    "make FIFO (named pipe)",
2853    "\
2854 This call creates a FIFO (named pipe) called C<path> with
2855 mode C<mode>.  It is just a convenient wrapper around
2856 C<guestfs_mknod>.");
2857
2858   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2859    [InitBasicFS, Always, TestOutputStruct (
2860       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2861        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2862    "make block device node",
2863    "\
2864 This call creates a block device node called C<path> with
2865 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2866 It is just a convenient wrapper around C<guestfs_mknod>.");
2867
2868   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2869    [InitBasicFS, Always, TestOutputStruct (
2870       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2871        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2872    "make char device node",
2873    "\
2874 This call creates a char device node called C<path> with
2875 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2876 It is just a convenient wrapper around C<guestfs_mknod>.");
2877
2878   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2879    [], (* XXX umask is one of those stateful things that we should
2880         * reset between each test.
2881         *)
2882    "set file mode creation mask (umask)",
2883    "\
2884 This function sets the mask used for creating new files and
2885 device nodes to C<mask & 0777>.
2886
2887 Typical umask values would be C<022> which creates new files
2888 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2889 C<002> which creates new files with permissions like
2890 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2891
2892 The default umask is C<022>.  This is important because it
2893 means that directories and device nodes will be created with
2894 C<0644> or C<0755> mode even if you specify C<0777>.
2895
2896 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2897
2898 This call returns the previous umask.");
2899
2900   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2901    [],
2902    "read directories entries",
2903    "\
2904 This returns the list of directory entries in directory C<dir>.
2905
2906 All entries in the directory are returned, including C<.> and
2907 C<..>.  The entries are I<not> sorted, but returned in the same
2908 order as the underlying filesystem.
2909
2910 Also this call returns basic file type information about each
2911 file.  The C<ftyp> field will contain one of the following characters:
2912
2913 =over 4
2914
2915 =item 'b'
2916
2917 Block special
2918
2919 =item 'c'
2920
2921 Char special
2922
2923 =item 'd'
2924
2925 Directory
2926
2927 =item 'f'
2928
2929 FIFO (named pipe)
2930
2931 =item 'l'
2932
2933 Symbolic link
2934
2935 =item 'r'
2936
2937 Regular file
2938
2939 =item 's'
2940
2941 Socket
2942
2943 =item 'u'
2944
2945 Unknown file type
2946
2947 =item '?'
2948
2949 The L<readdir(3)> returned a C<d_type> field with an
2950 unexpected value
2951
2952 =back
2953
2954 This function is primarily intended for use by programs.  To
2955 get a simple list of names, use C<guestfs_ls>.  To get a printable
2956 directory for human consumption, use C<guestfs_ll>.");
2957
2958   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2959    [],
2960    "create partitions on a block device",
2961    "\
2962 This is a simplified interface to the C<guestfs_sfdisk>
2963 command, where partition sizes are specified in megabytes
2964 only (rounded to the nearest cylinder) and you don't need
2965 to specify the cyls, heads and sectors parameters which
2966 were rarely if ever used anyway.
2967
2968 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
2969
2970   ("zfile", (RString "description", [String "method"; Pathname "path"]), 140, [DeprecatedBy "file"],
2971    [],
2972    "determine file type inside a compressed file",
2973    "\
2974 This command runs C<file> after first decompressing C<path>
2975 using C<method>.
2976
2977 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
2978
2979 Since 1.0.63, use C<guestfs_file> instead which can now
2980 process compressed files.");
2981
2982   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
2983    [],
2984    "list extended attributes of a file or directory",
2985    "\
2986 This call lists the extended attributes of the file or directory
2987 C<path>.
2988
2989 At the system call level, this is a combination of the
2990 L<listxattr(2)> and L<getxattr(2)> calls.
2991
2992 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
2993
2994   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
2995    [],
2996    "list extended attributes of a file or directory",
2997    "\
2998 This is the same as C<guestfs_getxattrs>, but if C<path>
2999 is a symbolic link, then it returns the extended attributes
3000 of the link itself.");
3001
3002   ("setxattr", (RErr, [String "xattr";
3003                        String "val"; Int "vallen"; (* will be BufferIn *)
3004                        Pathname "path"]), 143, [],
3005    [],
3006    "set extended attribute of a file or directory",
3007    "\
3008 This call sets the extended attribute named C<xattr>
3009 of the file C<path> to the value C<val> (of length C<vallen>).
3010 The value is arbitrary 8 bit data.
3011
3012 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3013
3014   ("lsetxattr", (RErr, [String "xattr";
3015                         String "val"; Int "vallen"; (* will be BufferIn *)
3016                         Pathname "path"]), 144, [],
3017    [],
3018    "set extended attribute of a file or directory",
3019    "\
3020 This is the same as C<guestfs_setxattr>, but if C<path>
3021 is a symbolic link, then it sets an extended attribute
3022 of the link itself.");
3023
3024   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3025    [],
3026    "remove extended attribute of a file or directory",
3027    "\
3028 This call removes the extended attribute named C<xattr>
3029 of the file C<path>.
3030
3031 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3032
3033   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3034    [],
3035    "remove extended attribute of a file or directory",
3036    "\
3037 This is the same as C<guestfs_removexattr>, but if C<path>
3038 is a symbolic link, then it removes an extended attribute
3039 of the link itself.");
3040
3041   ("mountpoints", (RHashtable "mps", []), 147, [],
3042    [],
3043    "show mountpoints",
3044    "\
3045 This call is similar to C<guestfs_mounts>.  That call returns
3046 a list of devices.  This one returns a hash table (map) of
3047 device name to directory where the device is mounted.");
3048
3049   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3050   (* This is a special case: while you would expect a parameter
3051    * of type "Pathname", that doesn't work, because it implies
3052    * NEED_ROOT in the generated calling code in stubs.c, and
3053    * this function cannot use NEED_ROOT.
3054    *)
3055    [],
3056    "create a mountpoint",
3057    "\
3058 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3059 specialized calls that can be used to create extra mountpoints
3060 before mounting the first filesystem.
3061
3062 These calls are I<only> necessary in some very limited circumstances,
3063 mainly the case where you want to mount a mix of unrelated and/or
3064 read-only filesystems together.
3065
3066 For example, live CDs often contain a \"Russian doll\" nest of
3067 filesystems, an ISO outer layer, with a squashfs image inside, with
3068 an ext2/3 image inside that.  You can unpack this as follows
3069 in guestfish:
3070
3071  add-ro Fedora-11-i686-Live.iso
3072  run
3073  mkmountpoint /cd
3074  mkmountpoint /squash
3075  mkmountpoint /ext3
3076  mount /dev/sda /cd
3077  mount-loop /cd/LiveOS/squashfs.img /squash
3078  mount-loop /squash/LiveOS/ext3fs.img /ext3
3079
3080 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3081
3082   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3083    [],
3084    "remove a mountpoint",
3085    "\
3086 This calls removes a mountpoint that was previously created
3087 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3088 for full details.");
3089
3090   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3091    [InitSquashFS, Always, TestOutputBuffer (
3092       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3093    "read a file",
3094    "\
3095 This calls returns the contents of the file C<path> as a
3096 buffer.
3097
3098 Unlike C<guestfs_cat>, this function can correctly
3099 handle files that contain embedded ASCII NUL characters.
3100 However unlike C<guestfs_download>, this function is limited
3101 in the total size of file that can be handled.");
3102
3103   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3104    [InitSquashFS, Always, TestOutputList (
3105       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3106     InitSquashFS, Always, TestOutputList (
3107       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3108    "return lines matching a pattern",
3109    "\
3110 This calls the external C<grep> program and returns the
3111 matching lines.");
3112
3113   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3114    [InitSquashFS, Always, TestOutputList (
3115       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3116    "return lines matching a pattern",
3117    "\
3118 This calls the external C<egrep> program and returns the
3119 matching lines.");
3120
3121   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3122    [InitSquashFS, Always, TestOutputList (
3123       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3124    "return lines matching a pattern",
3125    "\
3126 This calls the external C<fgrep> program and returns the
3127 matching lines.");
3128
3129   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3130    [InitSquashFS, Always, TestOutputList (
3131       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3132    "return lines matching a pattern",
3133    "\
3134 This calls the external C<grep -i> program and returns the
3135 matching lines.");
3136
3137   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3138    [InitSquashFS, Always, TestOutputList (
3139       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3140    "return lines matching a pattern",
3141    "\
3142 This calls the external C<egrep -i> program and returns the
3143 matching lines.");
3144
3145   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3146    [InitSquashFS, Always, TestOutputList (
3147       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3148    "return lines matching a pattern",
3149    "\
3150 This calls the external C<fgrep -i> program and returns the
3151 matching lines.");
3152
3153   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3154    [InitSquashFS, Always, TestOutputList (
3155       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3156    "return lines matching a pattern",
3157    "\
3158 This calls the external C<zgrep> program and returns the
3159 matching lines.");
3160
3161   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3162    [InitSquashFS, Always, TestOutputList (
3163       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3164    "return lines matching a pattern",
3165    "\
3166 This calls the external C<zegrep> program and returns the
3167 matching lines.");
3168
3169   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3170    [InitSquashFS, Always, TestOutputList (
3171       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3172    "return lines matching a pattern",
3173    "\
3174 This calls the external C<zfgrep> program and returns the
3175 matching lines.");
3176
3177   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3178    [InitSquashFS, Always, TestOutputList (
3179       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3180    "return lines matching a pattern",
3181    "\
3182 This calls the external C<zgrep -i> program and returns the
3183 matching lines.");
3184
3185   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3186    [InitSquashFS, Always, TestOutputList (
3187       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3188    "return lines matching a pattern",
3189    "\
3190 This calls the external C<zegrep -i> program and returns the
3191 matching lines.");
3192
3193   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3194    [InitSquashFS, Always, TestOutputList (
3195       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3196    "return lines matching a pattern",
3197    "\
3198 This calls the external C<zfgrep -i> program and returns the
3199 matching lines.");
3200
3201   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3202    [InitSquashFS, Always, TestOutput (
3203       [["realpath"; "/../directory"]], "/directory")],
3204    "canonicalized absolute pathname",
3205    "\
3206 Return the canonicalized absolute pathname of C<path>.  The
3207 returned path has no C<.>, C<..> or symbolic link path elements.");
3208
3209   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3210    [InitBasicFS, Always, TestOutputStruct (
3211       [["touch"; "/a"];
3212        ["ln"; "/a"; "/b"];
3213        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3214    "create a hard link",
3215    "\
3216 This command creates a hard link using the C<ln> command.");
3217
3218   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3219    [InitBasicFS, Always, TestOutputStruct (
3220       [["touch"; "/a"];
3221        ["touch"; "/b"];
3222        ["ln_f"; "/a"; "/b"];
3223        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3224    "create a hard link",
3225    "\
3226 This command creates a hard link using the C<ln -f> command.
3227 The C<-f> option removes the link (C<linkname>) if it exists already.");
3228
3229   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3230    [InitBasicFS, Always, TestOutputStruct (
3231       [["touch"; "/a"];
3232        ["ln_s"; "a"; "/b"];
3233        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3234    "create a symbolic link",
3235    "\
3236 This command creates a symbolic link using the C<ln -s> command.");
3237
3238   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3239    [InitBasicFS, Always, TestOutput (
3240       [["mkdir_p"; "/a/b"];
3241        ["touch"; "/a/b/c"];
3242        ["ln_sf"; "../d"; "/a/b/c"];
3243        ["readlink"; "/a/b/c"]], "../d")],
3244    "create a symbolic link",
3245    "\
3246 This command creates a symbolic link using the C<ln -sf> command,
3247 The C<-f> option removes the link (C<linkname>) if it exists already.");
3248
3249   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3250    [] (* XXX tested above *),
3251    "read the target of a symbolic link",
3252    "\
3253 This command reads the target of a symbolic link.");
3254
3255   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3256    [InitBasicFS, Always, TestOutputStruct (
3257       [["fallocate"; "/a"; "1000000"];
3258        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3259    "preallocate a file in the guest filesystem",
3260    "\
3261 This command preallocates a file (containing zero bytes) named
3262 C<path> of size C<len> bytes.  If the file exists already, it
3263 is overwritten.
3264
3265 Do not confuse this with the guestfish-specific
3266 C<alloc> command which allocates a file in the host and
3267 attaches it as a device.");
3268
3269   ("swapon_device", (RErr, [Device "device"]), 170, [],
3270    [InitPartition, Always, TestRun (
3271       [["mkswap"; "/dev/sda1"];
3272        ["swapon_device"; "/dev/sda1"];
3273        ["swapoff_device"; "/dev/sda1"]])],
3274    "enable swap on device",
3275    "\
3276 This command enables the libguestfs appliance to use the
3277 swap device or partition named C<device>.  The increased
3278 memory is made available for all commands, for example
3279 those run using C<guestfs_command> or C<guestfs_sh>.
3280
3281 Note that you should not swap to existing guest swap
3282 partitions unless you know what you are doing.  They may
3283 contain hibernation information, or other information that
3284 the guest doesn't want you to trash.  You also risk leaking
3285 information about the host to the guest this way.  Instead,
3286 attach a new host device to the guest and swap on that.");
3287
3288   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3289    [], (* XXX tested by swapon_device *)
3290    "disable swap on device",
3291    "\
3292 This command disables the libguestfs appliance swap
3293 device or partition named C<device>.
3294 See C<guestfs_swapon_device>.");
3295
3296   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3297    [InitBasicFS, Always, TestRun (
3298       [["fallocate"; "/swap"; "8388608"];
3299        ["mkswap_file"; "/swap"];
3300        ["swapon_file"; "/swap"];
3301        ["swapoff_file"; "/swap"]])],
3302    "enable swap on file",
3303    "\
3304 This command enables swap to a file.
3305 See C<guestfs_swapon_device> for other notes.");
3306
3307   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3308    [], (* XXX tested by swapon_file *)
3309    "disable swap on file",
3310    "\
3311 This command disables the libguestfs appliance swap on file.");
3312
3313   ("swapon_label", (RErr, [String "label"]), 174, [],
3314    [InitEmpty, Always, TestRun (
3315       [["sfdiskM"; "/dev/sdb"; ","];
3316        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3317        ["swapon_label"; "swapit"];
3318        ["swapoff_label"; "swapit"];
3319        ["zero"; "/dev/sdb"];
3320        ["blockdev_rereadpt"; "/dev/sdb"]])],
3321    "enable swap on labeled swap partition",
3322    "\
3323 This command enables swap to a labeled swap partition.
3324 See C<guestfs_swapon_device> for other notes.");
3325
3326   ("swapoff_label", (RErr, [String "label"]), 175, [],
3327    [], (* XXX tested by swapon_label *)
3328    "disable swap on labeled swap partition",
3329    "\
3330 This command disables the libguestfs appliance swap on
3331 labeled swap partition.");
3332
3333   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3334    (let uuid = uuidgen () in
3335     [InitEmpty, Always, TestRun (
3336        [["mkswap_U"; uuid; "/dev/sdb"];
3337         ["swapon_uuid"; uuid];
3338         ["swapoff_uuid"; uuid]])]),
3339    "enable swap on swap partition by UUID",
3340    "\
3341 This command enables swap to a swap partition with the given UUID.
3342 See C<guestfs_swapon_device> for other notes.");
3343
3344   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3345    [], (* XXX tested by swapon_uuid *)
3346    "disable swap on swap partition by UUID",
3347    "\
3348 This command disables the libguestfs appliance swap partition
3349 with the given UUID.");
3350
3351   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3352    [InitBasicFS, Always, TestRun (
3353       [["fallocate"; "/swap"; "8388608"];
3354        ["mkswap_file"; "/swap"]])],
3355    "create a swap file",
3356    "\
3357 Create a swap file.
3358
3359 This command just writes a swap file signature to an existing
3360 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3361
3362   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3363    [InitSquashFS, Always, TestRun (
3364       [["inotify_init"; "0"]])],
3365    "create an inotify handle",
3366    "\
3367 This command creates a new inotify handle.
3368 The inotify subsystem can be used to notify events which happen to
3369 objects in the guest filesystem.
3370
3371 C<maxevents> is the maximum number of events which will be
3372 queued up between calls to C<guestfs_inotify_read> or
3373 C<guestfs_inotify_files>.
3374 If this is passed as C<0>, then the kernel (or previously set)
3375 default is used.  For Linux 2.6.29 the default was 16384 events.
3376 Beyond this limit, the kernel throws away events, but records
3377 the fact that it threw them away by setting a flag
3378 C<IN_Q_OVERFLOW> in the returned structure list (see
3379 C<guestfs_inotify_read>).
3380
3381 Before any events are generated, you have to add some
3382 watches to the internal watch list.  See:
3383 C<guestfs_inotify_add_watch>,
3384 C<guestfs_inotify_rm_watch> and
3385 C<guestfs_inotify_watch_all>.
3386
3387 Queued up events should be read periodically by calling
3388 C<guestfs_inotify_read>
3389 (or C<guestfs_inotify_files> which is just a helpful
3390 wrapper around C<guestfs_inotify_read>).  If you don't
3391 read the events out often enough then you risk the internal
3392 queue overflowing.
3393
3394 The handle should be closed after use by calling
3395 C<guestfs_inotify_close>.  This also removes any
3396 watches automatically.
3397
3398 See also L<inotify(7)> for an overview of the inotify interface
3399 as exposed by the Linux kernel, which is roughly what we expose
3400 via libguestfs.  Note that there is one global inotify handle
3401 per libguestfs instance.");
3402
3403   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3404    [InitBasicFS, Always, TestOutputList (
3405       [["inotify_init"; "0"];
3406        ["inotify_add_watch"; "/"; "1073741823"];
3407        ["touch"; "/a"];
3408        ["touch"; "/b"];
3409        ["inotify_files"]], ["a"; "b"])],
3410    "add an inotify watch",
3411    "\
3412 Watch C<path> for the events listed in C<mask>.
3413
3414 Note that if C<path> is a directory then events within that
3415 directory are watched, but this does I<not> happen recursively
3416 (in subdirectories).
3417
3418 Note for non-C or non-Linux callers: the inotify events are
3419 defined by the Linux kernel ABI and are listed in
3420 C</usr/include/sys/inotify.h>.");
3421
3422   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3423    [],
3424    "remove an inotify watch",
3425    "\
3426 Remove a previously defined inotify watch.
3427 See C<guestfs_inotify_add_watch>.");
3428
3429   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3430    [],
3431    "return list of inotify events",
3432    "\
3433 Return the complete queue of events that have happened
3434 since the previous read call.
3435
3436 If no events have happened, this returns an empty list.
3437
3438 I<Note>: In order to make sure that all events have been
3439 read, you must call this function repeatedly until it
3440 returns an empty list.  The reason is that the call will
3441 read events up to the maximum appliance-to-host message
3442 size and leave remaining events in the queue.");
3443
3444   ("inotify_files", (RStringList "paths", []), 183, [],
3445    [],
3446    "return list of watched files that had events",
3447    "\
3448 This function is a helpful wrapper around C<guestfs_inotify_read>
3449 which just returns a list of pathnames of objects that were
3450 touched.  The returned pathnames are sorted and deduplicated.");
3451
3452   ("inotify_close", (RErr, []), 184, [],
3453    [],
3454    "close the inotify handle",
3455    "\
3456 This closes the inotify handle which was previously
3457 opened by inotify_init.  It removes all watches, throws
3458 away any pending events, and deallocates all resources.");
3459
3460   ("setcon", (RErr, [String "context"]), 185, [],
3461    [],
3462    "set SELinux security context",
3463    "\
3464 This sets the SELinux security context of the daemon
3465 to the string C<context>.
3466
3467 See the documentation about SELINUX in L<guestfs(3)>.");
3468
3469   ("getcon", (RString "context", []), 186, [],
3470    [],
3471    "get SELinux security context",
3472    "\
3473 This gets the SELinux security context of the daemon.
3474
3475 See the documentation about SELINUX in L<guestfs(3)>,
3476 and C<guestfs_setcon>");
3477
3478   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3479    [InitEmpty, Always, TestOutput (
3480       [["sfdiskM"; "/dev/sda"; ","];
3481        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3482        ["mount"; "/dev/sda1"; "/"];
3483        ["write_file"; "/new"; "new file contents"; "0"];
3484        ["cat"; "/new"]], "new file contents")],
3485    "make a filesystem with block size",
3486    "\
3487 This call is similar to C<guestfs_mkfs>, but it allows you to
3488 control the block size of the resulting filesystem.  Supported
3489 block sizes depend on the filesystem type, but typically they
3490 are C<1024>, C<2048> or C<4096> only.");
3491
3492   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3493    [InitEmpty, Always, TestOutput (
3494       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3495        ["mke2journal"; "4096"; "/dev/sda1"];
3496        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3497        ["mount"; "/dev/sda2"; "/"];
3498        ["write_file"; "/new"; "new file contents"; "0"];
3499        ["cat"; "/new"]], "new file contents")],
3500    "make ext2/3/4 external journal",
3501    "\
3502 This creates an ext2 external journal on C<device>.  It is equivalent
3503 to the command:
3504
3505  mke2fs -O journal_dev -b blocksize device");
3506
3507   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3508    [InitEmpty, Always, TestOutput (
3509       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3510        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3511        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3512        ["mount"; "/dev/sda2"; "/"];
3513        ["write_file"; "/new"; "new file contents"; "0"];
3514        ["cat"; "/new"]], "new file contents")],
3515    "make ext2/3/4 external journal with label",
3516    "\
3517 This creates an ext2 external journal on C<device> with label C<label>.");
3518
3519   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3520    (let uuid = uuidgen () in
3521     [InitEmpty, Always, TestOutput (
3522        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3523         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3524         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3525         ["mount"; "/dev/sda2"; "/"];
3526         ["write_file"; "/new"; "new file contents"; "0"];
3527         ["cat"; "/new"]], "new file contents")]),
3528    "make ext2/3/4 external journal with UUID",
3529    "\
3530 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3531
3532   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3533    [],
3534    "make ext2/3/4 filesystem with external journal",
3535    "\
3536 This creates an ext2/3/4 filesystem on C<device> with
3537 an external journal on C<journal>.  It is equivalent
3538 to the command:
3539
3540  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3541
3542 See also C<guestfs_mke2journal>.");
3543
3544   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3545    [],
3546    "make ext2/3/4 filesystem with external journal",
3547    "\
3548 This creates an ext2/3/4 filesystem on C<device> with
3549 an external journal on the journal labeled C<label>.
3550
3551 See also C<guestfs_mke2journal_L>.");
3552
3553   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3554    [],
3555    "make ext2/3/4 filesystem with external journal",
3556    "\
3557 This creates an ext2/3/4 filesystem on C<device> with
3558 an external journal on the journal with UUID C<uuid>.
3559
3560 See also C<guestfs_mke2journal_U>.");
3561
3562 ]
3563
3564 let all_functions = non_daemon_functions @ daemon_functions
3565
3566 (* In some places we want the functions to be displayed sorted
3567  * alphabetically, so this is useful:
3568  *)
3569 let all_functions_sorted =
3570   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3571                compare n1 n2) all_functions
3572
3573 (* Field types for structures. *)
3574 type field =
3575   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3576   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3577   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3578   | FUInt32
3579   | FInt32
3580   | FUInt64
3581   | FInt64
3582   | FBytes                      (* Any int measure that counts bytes. *)
3583   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3584   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3585
3586 (* Because we generate extra parsing code for LVM command line tools,
3587  * we have to pull out the LVM columns separately here.
3588  *)
3589 let lvm_pv_cols = [
3590   "pv_name", FString;
3591   "pv_uuid", FUUID;
3592   "pv_fmt", FString;
3593   "pv_size", FBytes;
3594   "dev_size", FBytes;
3595   "pv_free", FBytes;
3596   "pv_used", FBytes;
3597   "pv_attr", FString (* XXX *);
3598   "pv_pe_count", FInt64;
3599   "pv_pe_alloc_count", FInt64;
3600   "pv_tags", FString;
3601   "pe_start", FBytes;
3602   "pv_mda_count", FInt64;
3603   "pv_mda_free", FBytes;
3604   (* Not in Fedora 10:
3605      "pv_mda_size", FBytes;
3606   *)
3607 ]
3608 let lvm_vg_cols = [
3609   "vg_name", FString;
3610   "vg_uuid", FUUID;
3611   "vg_fmt", FString;
3612   "vg_attr", FString (* XXX *);
3613   "vg_size", FBytes;
3614   "vg_free", FBytes;
3615   "vg_sysid", FString;
3616   "vg_extent_size", FBytes;
3617   "vg_extent_count", FInt64;
3618   "vg_free_count", FInt64;
3619   "max_lv", FInt64;
3620   "max_pv", FInt64;
3621   "pv_count", FInt64;
3622   "lv_count", FInt64;
3623   "snap_count", FInt64;
3624   "vg_seqno", FInt64;
3625   "vg_tags", FString;
3626   "vg_mda_count", FInt64;
3627   "vg_mda_free", FBytes;
3628   (* Not in Fedora 10:
3629      "vg_mda_size", FBytes;
3630   *)
3631 ]
3632 let lvm_lv_cols = [
3633   "lv_name", FString;
3634   "lv_uuid", FUUID;
3635   "lv_attr", FString (* XXX *);
3636   "lv_major", FInt64;
3637   "lv_minor", FInt64;
3638   "lv_kernel_major", FInt64;
3639   "lv_kernel_minor", FInt64;
3640   "lv_size", FBytes;
3641   "seg_count", FInt64;
3642   "origin", FString;
3643   "snap_percent", FOptPercent;
3644   "copy_percent", FOptPercent;
3645   "move_pv", FString;
3646   "lv_tags", FString;
3647   "mirror_log", FString;
3648   "modules", FString;
3649 ]
3650
3651 (* Names and fields in all structures (in RStruct and RStructList)
3652  * that we support.
3653  *)
3654 let structs = [
3655   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3656    * not use this struct in any new code.
3657    *)
3658   "int_bool", [
3659     "i", FInt32;                (* for historical compatibility *)
3660     "b", FInt32;                (* for historical compatibility *)
3661   ];
3662
3663   (* LVM PVs, VGs, LVs. *)
3664   "lvm_pv", lvm_pv_cols;
3665   "lvm_vg", lvm_vg_cols;
3666   "lvm_lv", lvm_lv_cols;
3667
3668   (* Column names and types from stat structures.
3669    * NB. Can't use things like 'st_atime' because glibc header files
3670    * define some of these as macros.  Ugh.
3671    *)
3672   "stat", [
3673     "dev", FInt64;
3674     "ino", FInt64;
3675     "mode", FInt64;
3676     "nlink", FInt64;
3677     "uid", FInt64;
3678     "gid", FInt64;
3679     "rdev", FInt64;
3680     "size", FInt64;
3681     "blksize", FInt64;
3682     "blocks", FInt64;
3683     "atime", FInt64;
3684     "mtime", FInt64;
3685     "ctime", FInt64;
3686   ];
3687   "statvfs", [
3688     "bsize", FInt64;
3689     "frsize", FInt64;
3690     "blocks", FInt64;
3691     "bfree", FInt64;
3692     "bavail", FInt64;
3693     "files", FInt64;
3694     "ffree", FInt64;
3695     "favail", FInt64;
3696     "fsid", FInt64;
3697     "flag", FInt64;
3698     "namemax", FInt64;
3699   ];
3700
3701   (* Column names in dirent structure. *)
3702   "dirent", [
3703     "ino", FInt64;
3704     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3705     "ftyp", FChar;
3706     "name", FString;
3707   ];
3708
3709   (* Version numbers. *)
3710   "version", [
3711     "major", FInt64;
3712     "minor", FInt64;
3713     "release", FInt64;
3714     "extra", FString;
3715   ];
3716
3717   (* Extended attribute. *)
3718   "xattr", [
3719     "attrname", FString;
3720     "attrval", FBuffer;
3721   ];
3722
3723   (* Inotify events. *)
3724   "inotify_event", [
3725     "in_wd", FInt64;
3726     "in_mask", FUInt32;
3727     "in_cookie", FUInt32;
3728     "in_name", FString;
3729   ];
3730 ] (* end of structs *)
3731
3732 (* Ugh, Java has to be different ..
3733  * These names are also used by the Haskell bindings.
3734  *)
3735 let java_structs = [
3736   "int_bool", "IntBool";
3737   "lvm_pv", "PV";
3738   "lvm_vg", "VG";
3739   "lvm_lv", "LV";
3740   "stat", "Stat";
3741   "statvfs", "StatVFS";
3742   "dirent", "Dirent";
3743   "version", "Version";
3744   "xattr", "XAttr";
3745   "inotify_event", "INotifyEvent";
3746 ]
3747
3748 (* What structs are actually returned. *)
3749 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3750
3751 (* Returns a list of RStruct/RStructList structs that are returned
3752  * by any function.  Each element of returned list is a pair:
3753  *
3754  * (structname, RStructOnly)
3755  *    == there exists function which returns RStruct (_, structname)
3756  * (structname, RStructListOnly)
3757  *    == there exists function which returns RStructList (_, structname)
3758  * (structname, RStructAndList)
3759  *    == there are functions returning both RStruct (_, structname)
3760  *                                      and RStructList (_, structname)
3761  *)
3762 let rstructs_used =
3763   (* ||| is a "logical OR" for rstructs_used_t *)
3764   let (|||) a b =
3765     match a, b with
3766     | RStructAndList, _
3767     | _, RStructAndList -> RStructAndList
3768     | RStructOnly, RStructListOnly
3769     | RStructListOnly, RStructOnly -> RStructAndList
3770     | RStructOnly, RStructOnly -> RStructOnly
3771     | RStructListOnly, RStructListOnly -> RStructListOnly
3772   in
3773
3774   let h = Hashtbl.create 13 in
3775
3776   (* if elem->oldv exists, update entry using ||| operator,
3777    * else just add elem->newv to the hash
3778    *)
3779   let update elem newv =
3780     try  let oldv = Hashtbl.find h elem in
3781          Hashtbl.replace h elem (newv ||| oldv)
3782     with Not_found -> Hashtbl.add h elem newv
3783   in
3784
3785   List.iter (
3786     fun (_, style, _, _, _, _, _) ->
3787       match fst style with
3788       | RStruct (_, structname) -> update structname RStructOnly
3789       | RStructList (_, structname) -> update structname RStructListOnly
3790       | _ -> ()
3791   ) all_functions;
3792
3793   (* return key->values as a list of (key,value) *)
3794   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3795
3796 (* debug:
3797 let () =
3798   List.iter (
3799     function
3800     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3801     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3802     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3803   ) rstructs_used
3804 *)
3805
3806 (* Used for testing language bindings. *)
3807 type callt =
3808   | CallString of string
3809   | CallOptString of string option
3810   | CallStringList of string list
3811   | CallInt of int
3812   | CallBool of bool
3813
3814 (* Used to memoize the result of pod2text. *)
3815 let pod2text_memo_filename = "src/.pod2text.data"
3816 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3817   try
3818     let chan = open_in pod2text_memo_filename in
3819     let v = input_value chan in
3820     close_in chan;
3821     v
3822   with
3823     _ -> Hashtbl.create 13
3824
3825 (* Useful functions.
3826  * Note we don't want to use any external OCaml libraries which
3827  * makes this a bit harder than it should be.
3828  *)
3829 let failwithf fs = ksprintf failwith fs
3830
3831 let replace_char s c1 c2 =
3832   let s2 = String.copy s in
3833   let r = ref false in
3834   for i = 0 to String.length s2 - 1 do
3835     if String.unsafe_get s2 i = c1 then (
3836       String.unsafe_set s2 i c2;
3837       r := true
3838     )
3839   done;
3840   if not !r then s else s2
3841
3842 let isspace c =
3843   c = ' '
3844   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3845
3846 let triml ?(test = isspace) str =
3847   let i = ref 0 in
3848   let n = ref (String.length str) in
3849   while !n > 0 && test str.[!i]; do
3850     decr n;
3851     incr i
3852   done;
3853   if !i = 0 then str
3854   else String.sub str !i !n
3855
3856 let trimr ?(test = isspace) str =
3857   let n = ref (String.length str) in
3858   while !n > 0 && test str.[!n-1]; do
3859     decr n
3860   done;
3861   if !n = String.length str then str
3862   else String.sub str 0 !n
3863
3864 let trim ?(test = isspace) str =
3865   trimr ~test (triml ~test str)
3866
3867 let rec find s sub =
3868   let len = String.length s in
3869   let sublen = String.length sub in
3870   let rec loop i =
3871     if i <= len-sublen then (
3872       let rec loop2 j =
3873         if j < sublen then (
3874           if s.[i+j] = sub.[j] then loop2 (j+1)
3875           else -1
3876         ) else
3877           i (* found *)
3878       in
3879       let r = loop2 0 in
3880       if r = -1 then loop (i+1) else r
3881     ) else
3882       -1 (* not found *)
3883   in
3884   loop 0
3885
3886 let rec replace_str s s1 s2 =
3887   let len = String.length s in
3888   let sublen = String.length s1 in
3889   let i = find s s1 in
3890   if i = -1 then s
3891   else (
3892     let s' = String.sub s 0 i in
3893     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3894     s' ^ s2 ^ replace_str s'' s1 s2
3895   )
3896
3897 let rec string_split sep str =
3898   let len = String.length str in
3899   let seplen = String.length sep in
3900   let i = find str sep in
3901   if i = -1 then [str]
3902   else (
3903     let s' = String.sub str 0 i in
3904     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3905     s' :: string_split sep s''
3906   )
3907
3908 let files_equal n1 n2 =
3909   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3910   match Sys.command cmd with
3911   | 0 -> true
3912   | 1 -> false
3913   | i -> failwithf "%s: failed with error code %d" cmd i
3914
3915 let rec filter_map f = function
3916   | [] -> []
3917   | x :: xs ->
3918       match f x with
3919       | Some y -> y :: filter_map f xs
3920       | None -> filter_map f xs
3921
3922 let rec find_map f = function
3923   | [] -> raise Not_found
3924   | x :: xs ->
3925       match f x with
3926       | Some y -> y
3927       | None -> find_map f xs
3928
3929 let iteri f xs =
3930   let rec loop i = function
3931     | [] -> ()
3932     | x :: xs -> f i x; loop (i+1) xs
3933   in
3934   loop 0 xs
3935
3936 let mapi f xs =
3937   let rec loop i = function
3938     | [] -> []
3939     | x :: xs -> let r = f i x in r :: loop (i+1) xs
3940   in
3941   loop 0 xs
3942
3943 let name_of_argt = function
3944   | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | Bool n | Int n
3945   | FileIn n | FileOut n -> n
3946
3947 let java_name_of_struct typ =
3948   try List.assoc typ java_structs
3949   with Not_found ->
3950     failwithf
3951       "java_name_of_struct: no java_structs entry corresponding to %s" typ
3952
3953 let cols_of_struct typ =
3954   try List.assoc typ structs
3955   with Not_found ->
3956     failwithf "cols_of_struct: unknown struct %s" typ
3957
3958 let seq_of_test = function
3959   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3960   | TestOutputListOfDevices (s, _)
3961   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3962   | TestOutputTrue s | TestOutputFalse s
3963   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3964   | TestOutputStruct (s, _)
3965   | TestLastFail s -> s
3966
3967 (* Handling for function flags. *)
3968 let protocol_limit_warning =
3969   "Because of the message protocol, there is a transfer limit
3970 of somewhere between 2MB and 4MB.  To transfer large files you should use
3971 FTP."
3972
3973 let danger_will_robinson =
3974   "B<This command is dangerous.  Without careful use you
3975 can easily destroy all your data>."
3976
3977 let deprecation_notice flags =
3978   try
3979     let alt =
3980       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
3981     let txt =
3982       sprintf "This function is deprecated.
3983 In new code, use the C<%s> call instead.
3984
3985 Deprecated functions will not be removed from the API, but the
3986 fact that they are deprecated indicates that there are problems
3987 with correct use of these functions." alt in
3988     Some txt
3989   with
3990     Not_found -> None
3991
3992 (* Check function names etc. for consistency. *)
3993 let check_functions () =
3994   let contains_uppercase str =
3995     let len = String.length str in
3996     let rec loop i =
3997       if i >= len then false
3998       else (
3999         let c = str.[i] in
4000         if c >= 'A' && c <= 'Z' then true
4001         else loop (i+1)
4002       )
4003     in
4004     loop 0
4005   in
4006
4007   (* Check function names. *)
4008   List.iter (
4009     fun (name, _, _, _, _, _, _) ->
4010       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4011         failwithf "function name %s does not need 'guestfs' prefix" name;
4012       if name = "" then
4013         failwithf "function name is empty";
4014       if name.[0] < 'a' || name.[0] > 'z' then
4015         failwithf "function name %s must start with lowercase a-z" name;
4016       if String.contains name '-' then
4017         failwithf "function name %s should not contain '-', use '_' instead."
4018           name
4019   ) all_functions;
4020
4021   (* Check function parameter/return names. *)
4022   List.iter (
4023     fun (name, style, _, _, _, _, _) ->
4024       let check_arg_ret_name n =
4025         if contains_uppercase n then
4026           failwithf "%s param/ret %s should not contain uppercase chars"
4027             name n;
4028         if String.contains n '-' || String.contains n '_' then
4029           failwithf "%s param/ret %s should not contain '-' or '_'"
4030             name n;
4031         if n = "value" then
4032           failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
4033         if n = "int" || n = "char" || n = "short" || n = "long" then
4034           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4035         if n = "i" || n = "n" then
4036           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4037         if n = "argv" || n = "args" then
4038           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
4039       in
4040
4041       (match fst style with
4042        | RErr -> ()
4043        | RInt n | RInt64 n | RBool n
4044        | RConstString n | RConstOptString n | RString n
4045        | RStringList n | RStruct (n, _) | RStructList (n, _)
4046        | RHashtable n | RBufferOut n ->
4047            check_arg_ret_name n
4048       );
4049       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4050   ) all_functions;
4051
4052   (* Check short descriptions. *)
4053   List.iter (
4054     fun (name, _, _, _, _, shortdesc, _) ->
4055       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4056         failwithf "short description of %s should begin with lowercase." name;
4057       let c = shortdesc.[String.length shortdesc-1] in
4058       if c = '\n' || c = '.' then
4059         failwithf "short description of %s should not end with . or \\n." name
4060   ) all_functions;
4061
4062   (* Check long dscriptions. *)
4063   List.iter (
4064     fun (name, _, _, _, _, _, longdesc) ->
4065       if longdesc.[String.length longdesc-1] = '\n' then
4066         failwithf "long description of %s should not end with \\n." name
4067   ) all_functions;
4068
4069   (* Check proc_nrs. *)
4070   List.iter (
4071     fun (name, _, proc_nr, _, _, _, _) ->
4072       if proc_nr <= 0 then
4073         failwithf "daemon function %s should have proc_nr > 0" name
4074   ) daemon_functions;
4075
4076   List.iter (
4077     fun (name, _, proc_nr, _, _, _, _) ->
4078       if proc_nr <> -1 then
4079         failwithf "non-daemon function %s should have proc_nr -1" name
4080   ) non_daemon_functions;
4081
4082   let proc_nrs =
4083     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4084       daemon_functions in
4085   let proc_nrs =
4086     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4087   let rec loop = function
4088     | [] -> ()
4089     | [_] -> ()
4090     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4091         loop rest
4092     | (name1,nr1) :: (name2,nr2) :: _ ->
4093         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4094           name1 name2 nr1 nr2
4095   in
4096   loop proc_nrs;
4097
4098   (* Check tests. *)
4099   List.iter (
4100     function
4101       (* Ignore functions that have no tests.  We generate a
4102        * warning when the user does 'make check' instead.
4103        *)
4104     | name, _, _, _, [], _, _ -> ()
4105     | name, _, _, _, tests, _, _ ->
4106         let funcs =
4107           List.map (
4108             fun (_, _, test) ->
4109               match seq_of_test test with
4110               | [] ->
4111                   failwithf "%s has a test containing an empty sequence" name
4112               | cmds -> List.map List.hd cmds
4113           ) tests in
4114         let funcs = List.flatten funcs in
4115
4116         let tested = List.mem name funcs in
4117
4118         if not tested then
4119           failwithf "function %s has tests but does not test itself" name
4120   ) all_functions
4121
4122 (* 'pr' prints to the current output file. *)
4123 let chan = ref stdout
4124 let pr fs = ksprintf (output_string !chan) fs
4125
4126 (* Generate a header block in a number of standard styles. *)
4127 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4128 type license = GPLv2 | LGPLv2
4129
4130 let generate_header comment license =
4131   let c = match comment with
4132     | CStyle ->     pr "/* "; " *"
4133     | HashStyle ->  pr "# ";  "#"
4134     | OCamlStyle -> pr "(* "; " *"
4135     | HaskellStyle -> pr "{- "; "  " in
4136   pr "libguestfs generated file\n";
4137   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4138   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4139   pr "%s\n" c;
4140   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4141   pr "%s\n" c;
4142   (match license with
4143    | GPLv2 ->
4144        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4145        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4146        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4147        pr "%s (at your option) any later version.\n" c;
4148        pr "%s\n" c;
4149        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4150        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4151        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4152        pr "%s GNU General Public License for more details.\n" c;
4153        pr "%s\n" c;
4154        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4155        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4156        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4157
4158    | LGPLv2 ->
4159        pr "%s This library is free software; you can redistribute it and/or\n" c;
4160        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4161        pr "%s License as published by the Free Software Foundation; either\n" c;
4162        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4163        pr "%s\n" c;
4164        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4165        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4166        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4167        pr "%s Lesser General Public License for more details.\n" c;
4168        pr "%s\n" c;
4169        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4170        pr "%s License along with this library; if not, write to the Free Software\n" c;
4171        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4172   );
4173   (match comment with
4174    | CStyle -> pr " */\n"
4175    | HashStyle -> ()
4176    | OCamlStyle -> pr " *)\n"
4177    | HaskellStyle -> pr "-}\n"
4178   );
4179   pr "\n"
4180
4181 (* Start of main code generation functions below this line. *)
4182
4183 (* Generate the pod documentation for the C API. *)
4184 let rec generate_actions_pod () =
4185   List.iter (
4186     fun (shortname, style, _, flags, _, _, longdesc) ->
4187       if not (List.mem NotInDocs flags) then (
4188         let name = "guestfs_" ^ shortname in
4189         pr "=head2 %s\n\n" name;
4190         pr " ";
4191         generate_prototype ~extern:false ~handle:"handle" name style;
4192         pr "\n\n";
4193         pr "%s\n\n" longdesc;
4194         (match fst style with
4195          | RErr ->
4196              pr "This function returns 0 on success or -1 on error.\n\n"
4197          | RInt _ ->
4198              pr "On error this function returns -1.\n\n"
4199          | RInt64 _ ->
4200              pr "On error this function returns -1.\n\n"
4201          | RBool _ ->
4202              pr "This function returns a C truth value on success or -1 on error.\n\n"
4203          | RConstString _ ->
4204              pr "This function returns a string, or NULL on error.
4205 The string is owned by the guest handle and must I<not> be freed.\n\n"
4206          | RConstOptString _ ->
4207              pr "This function returns a string which may be NULL.
4208 There is way to return an error from this function.
4209 The string is owned by the guest handle and must I<not> be freed.\n\n"
4210          | RString _ ->
4211              pr "This function returns a string, or NULL on error.
4212 I<The caller must free the returned string after use>.\n\n"
4213          | RStringList _ ->
4214              pr "This function returns a NULL-terminated array of strings
4215 (like L<environ(3)>), or NULL if there was an error.
4216 I<The caller must free the strings and the array after use>.\n\n"
4217          | RStruct (_, typ) ->
4218              pr "This function returns a C<struct guestfs_%s *>,
4219 or NULL if there was an error.
4220 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4221          | RStructList (_, typ) ->
4222              pr "This function returns a C<struct guestfs_%s_list *>
4223 (see E<lt>guestfs-structs.hE<gt>),
4224 or NULL if there was an error.
4225 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4226          | RHashtable _ ->
4227              pr "This function returns a NULL-terminated array of
4228 strings, or NULL if there was an error.
4229 The array of strings will always have length C<2n+1>, where
4230 C<n> keys and values alternate, followed by the trailing NULL entry.
4231 I<The caller must free the strings and the array after use>.\n\n"
4232          | RBufferOut _ ->
4233              pr "This function returns a buffer, or NULL on error.
4234 The size of the returned buffer is written to C<*size_r>.
4235 I<The caller must free the returned buffer after use>.\n\n"
4236         );
4237         if List.mem ProtocolLimitWarning flags then
4238           pr "%s\n\n" protocol_limit_warning;
4239         if List.mem DangerWillRobinson flags then
4240           pr "%s\n\n" danger_will_robinson;
4241         match deprecation_notice flags with
4242         | None -> ()
4243         | Some txt -> pr "%s\n\n" txt
4244       )
4245   ) all_functions_sorted
4246
4247 and generate_structs_pod () =
4248   (* Structs documentation. *)
4249   List.iter (
4250     fun (typ, cols) ->
4251       pr "=head2 guestfs_%s\n" typ;
4252       pr "\n";
4253       pr " struct guestfs_%s {\n" typ;
4254       List.iter (
4255         function
4256         | name, FChar -> pr "   char %s;\n" name
4257         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4258         | name, FInt32 -> pr "   int32_t %s;\n" name
4259         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4260         | name, FInt64 -> pr "   int64_t %s;\n" name
4261         | name, FString -> pr "   char *%s;\n" name
4262         | name, FBuffer ->
4263             pr "   /* The next two fields describe a byte array. */\n";
4264             pr "   uint32_t %s_len;\n" name;
4265             pr "   char *%s;\n" name
4266         | name, FUUID ->
4267             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4268             pr "   char %s[32];\n" name
4269         | name, FOptPercent ->
4270             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4271             pr "   float %s;\n" name
4272       ) cols;
4273       pr " };\n";
4274       pr " \n";
4275       pr " struct guestfs_%s_list {\n" typ;
4276       pr "   uint32_t len; /* Number of elements in list. */\n";
4277       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4278       pr " };\n";
4279       pr " \n";
4280       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4281       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4282         typ typ;
4283       pr "\n"
4284   ) structs
4285
4286 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4287  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4288  *
4289  * We have to use an underscore instead of a dash because otherwise
4290  * rpcgen generates incorrect code.
4291  *
4292  * This header is NOT exported to clients, but see also generate_structs_h.
4293  *)
4294 and generate_xdr () =
4295   generate_header CStyle LGPLv2;
4296
4297   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4298   pr "typedef string str<>;\n";
4299   pr "\n";
4300
4301   (* Internal structures. *)
4302   List.iter (
4303     function
4304     | typ, cols ->
4305         pr "struct guestfs_int_%s {\n" typ;
4306         List.iter (function
4307                    | name, FChar -> pr "  char %s;\n" name
4308                    | name, FString -> pr "  string %s<>;\n" name
4309                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4310                    | name, FUUID -> pr "  opaque %s[32];\n" name
4311                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4312                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4313                    | name, FOptPercent -> pr "  float %s;\n" name
4314                   ) cols;
4315         pr "};\n";
4316         pr "\n";
4317         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4318         pr "\n";
4319   ) structs;
4320
4321   List.iter (
4322     fun (shortname, style, _, _, _, _, _) ->
4323       let name = "guestfs_" ^ shortname in
4324
4325       (match snd style with
4326        | [] -> ()
4327        | args ->
4328            pr "struct %s_args {\n" name;
4329            List.iter (
4330              function
4331              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4332              | OptString n -> pr "  str *%s;\n" n
4333              | StringList n -> pr "  str %s<>;\n" n
4334              | Bool n -> pr "  bool %s;\n" n
4335              | Int n -> pr "  int %s;\n" n
4336              | FileIn _ | FileOut _ -> ()
4337            ) args;
4338            pr "};\n\n"
4339       );
4340       (match fst style with
4341        | RErr -> ()
4342        | RInt n ->
4343            pr "struct %s_ret {\n" name;
4344            pr "  int %s;\n" n;
4345            pr "};\n\n"
4346        | RInt64 n ->
4347            pr "struct %s_ret {\n" name;
4348            pr "  hyper %s;\n" n;
4349            pr "};\n\n"
4350        | RBool n ->
4351            pr "struct %s_ret {\n" name;
4352            pr "  bool %s;\n" n;
4353            pr "};\n\n"
4354        | RConstString _ | RConstOptString _ ->
4355            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4356        | RString n ->
4357            pr "struct %s_ret {\n" name;
4358            pr "  string %s<>;\n" n;
4359            pr "};\n\n"
4360        | RStringList n ->
4361            pr "struct %s_ret {\n" name;
4362            pr "  str %s<>;\n" n;
4363            pr "};\n\n"
4364        | RStruct (n, typ) ->
4365            pr "struct %s_ret {\n" name;
4366            pr "  guestfs_int_%s %s;\n" typ n;
4367            pr "};\n\n"
4368        | RStructList (n, typ) ->
4369            pr "struct %s_ret {\n" name;
4370            pr "  guestfs_int_%s_list %s;\n" typ n;
4371            pr "};\n\n"
4372        | RHashtable n ->
4373            pr "struct %s_ret {\n" name;
4374            pr "  str %s<>;\n" n;
4375            pr "};\n\n"
4376        | RBufferOut n ->
4377            pr "struct %s_ret {\n" name;
4378            pr "  opaque %s<>;\n" n;
4379            pr "};\n\n"
4380       );
4381   ) daemon_functions;
4382
4383   (* Table of procedure numbers. *)
4384   pr "enum guestfs_procedure {\n";
4385   List.iter (
4386     fun (shortname, _, proc_nr, _, _, _, _) ->
4387       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4388   ) daemon_functions;
4389   pr "  GUESTFS_PROC_NR_PROCS\n";
4390   pr "};\n";
4391   pr "\n";
4392
4393   (* Having to choose a maximum message size is annoying for several
4394    * reasons (it limits what we can do in the API), but it (a) makes
4395    * the protocol a lot simpler, and (b) provides a bound on the size
4396    * of the daemon which operates in limited memory space.  For large
4397    * file transfers you should use FTP.
4398    *)
4399   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4400   pr "\n";
4401
4402   (* Message header, etc. *)
4403   pr "\
4404 /* The communication protocol is now documented in the guestfs(3)
4405  * manpage.
4406  */
4407
4408 const GUESTFS_PROGRAM = 0x2000F5F5;
4409 const GUESTFS_PROTOCOL_VERSION = 1;
4410
4411 /* These constants must be larger than any possible message length. */
4412 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4413 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4414
4415 enum guestfs_message_direction {
4416   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4417   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4418 };
4419
4420 enum guestfs_message_status {
4421   GUESTFS_STATUS_OK = 0,
4422   GUESTFS_STATUS_ERROR = 1
4423 };
4424
4425 const GUESTFS_ERROR_LEN = 256;
4426
4427 struct guestfs_message_error {
4428   string error_message<GUESTFS_ERROR_LEN>;
4429 };
4430
4431 struct guestfs_message_header {
4432   unsigned prog;                     /* GUESTFS_PROGRAM */
4433   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4434   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4435   guestfs_message_direction direction;
4436   unsigned serial;                   /* message serial number */
4437   guestfs_message_status status;
4438 };
4439
4440 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4441
4442 struct guestfs_chunk {
4443   int cancel;                        /* if non-zero, transfer is cancelled */
4444   /* data size is 0 bytes if the transfer has finished successfully */
4445   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4446 };
4447 "
4448
4449 (* Generate the guestfs-structs.h file. *)
4450 and generate_structs_h () =
4451   generate_header CStyle LGPLv2;
4452
4453   (* This is a public exported header file containing various
4454    * structures.  The structures are carefully written to have
4455    * exactly the same in-memory format as the XDR structures that
4456    * we use on the wire to the daemon.  The reason for creating
4457    * copies of these structures here is just so we don't have to
4458    * export the whole of guestfs_protocol.h (which includes much
4459    * unrelated and XDR-dependent stuff that we don't want to be
4460    * public, or required by clients).
4461    *
4462    * To reiterate, we will pass these structures to and from the
4463    * client with a simple assignment or memcpy, so the format
4464    * must be identical to what rpcgen / the RFC defines.
4465    *)
4466
4467   (* Public structures. *)
4468   List.iter (
4469     fun (typ, cols) ->
4470       pr "struct guestfs_%s {\n" typ;
4471       List.iter (
4472         function
4473         | name, FChar -> pr "  char %s;\n" name
4474         | name, FString -> pr "  char *%s;\n" name
4475         | name, FBuffer ->
4476             pr "  uint32_t %s_len;\n" name;
4477             pr "  char *%s;\n" name
4478         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4479         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4480         | name, FInt32 -> pr "  int32_t %s;\n" name
4481         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4482         | name, FInt64 -> pr "  int64_t %s;\n" name
4483         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4484       ) cols;
4485       pr "};\n";
4486       pr "\n";
4487       pr "struct guestfs_%s_list {\n" typ;
4488       pr "  uint32_t len;\n";
4489       pr "  struct guestfs_%s *val;\n" typ;
4490       pr "};\n";
4491       pr "\n";
4492       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4493       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4494       pr "\n"
4495   ) structs
4496
4497 (* Generate the guestfs-actions.h file. *)
4498 and generate_actions_h () =
4499   generate_header CStyle LGPLv2;
4500   List.iter (
4501     fun (shortname, style, _, _, _, _, _) ->
4502       let name = "guestfs_" ^ shortname in
4503       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4504         name style
4505   ) all_functions
4506
4507 (* Generate the client-side dispatch stubs. *)
4508 and generate_client_actions () =
4509   generate_header CStyle LGPLv2;
4510
4511   pr "\
4512 #include <stdio.h>
4513 #include <stdlib.h>
4514
4515 #include \"guestfs.h\"
4516 #include \"guestfs_protocol.h\"
4517
4518 #define error guestfs_error
4519 #define perrorf guestfs_perrorf
4520 #define safe_malloc guestfs_safe_malloc
4521 #define safe_realloc guestfs_safe_realloc
4522 #define safe_strdup guestfs_safe_strdup
4523 #define safe_memdup guestfs_safe_memdup
4524
4525 /* Check the return message from a call for validity. */
4526 static int
4527 check_reply_header (guestfs_h *g,
4528                     const struct guestfs_message_header *hdr,
4529                     int proc_nr, int serial)
4530 {
4531   if (hdr->prog != GUESTFS_PROGRAM) {
4532     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4533     return -1;
4534   }
4535   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4536     error (g, \"wrong protocol version (%%d/%%d)\",
4537            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4538     return -1;
4539   }
4540   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4541     error (g, \"unexpected message direction (%%d/%%d)\",
4542            hdr->direction, GUESTFS_DIRECTION_REPLY);
4543     return -1;
4544   }
4545   if (hdr->proc != proc_nr) {
4546     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4547     return -1;
4548   }
4549   if (hdr->serial != serial) {
4550     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4551     return -1;
4552   }
4553
4554   return 0;
4555 }
4556
4557 /* Check we are in the right state to run a high-level action. */
4558 static int
4559 check_state (guestfs_h *g, const char *caller)
4560 {
4561   if (!guestfs_is_ready (g)) {
4562     if (guestfs_is_config (g))
4563       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4564         caller);
4565     else if (guestfs_is_launching (g))
4566       error (g, \"%%s: call wait_ready() before using this function\",
4567         caller);
4568     else
4569       error (g, \"%%s called from the wrong state, %%d != READY\",
4570         caller, guestfs_get_state (g));
4571     return -1;
4572   }
4573   return 0;
4574 }
4575
4576 ";
4577
4578   (* Client-side stubs for each function. *)
4579   List.iter (
4580     fun (shortname, style, _, _, _, _, _) ->
4581       let name = "guestfs_" ^ shortname in
4582
4583       (* Generate the context struct which stores the high-level
4584        * state between callback functions.
4585        *)
4586       pr "struct %s_ctx {\n" shortname;
4587       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4588       pr "   * the callbacks as expected, and in the right sequence.\n";
4589       pr "   * 0 = not called, 1 = reply_cb called.\n";
4590       pr "   */\n";
4591       pr "  int cb_sequence;\n";
4592       pr "  struct guestfs_message_header hdr;\n";
4593       pr "  struct guestfs_message_error err;\n";
4594       (match fst style with
4595        | RErr -> ()
4596        | RConstString _ | RConstOptString _ ->
4597            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4598        | RInt _ | RInt64 _
4599        | RBool _ | RString _ | RStringList _
4600        | RStruct _ | RStructList _
4601        | RHashtable _ | RBufferOut _ ->
4602            pr "  struct %s_ret ret;\n" name
4603       );
4604       pr "};\n";
4605       pr "\n";
4606
4607       (* Generate the reply callback function. *)
4608       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4609       pr "{\n";
4610       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4611       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4612       pr "\n";
4613       pr "  /* This should definitely not happen. */\n";
4614       pr "  if (ctx->cb_sequence != 0) {\n";
4615       pr "    ctx->cb_sequence = 9999;\n";
4616       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4617       pr "    return;\n";
4618       pr "  }\n";
4619       pr "\n";
4620       pr "  ml->main_loop_quit (ml, g);\n";
4621       pr "\n";
4622       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4623       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4624       pr "    return;\n";
4625       pr "  }\n";
4626       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4627       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4628       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4629         name;
4630       pr "      return;\n";
4631       pr "    }\n";
4632       pr "    goto done;\n";
4633       pr "  }\n";
4634
4635       (match fst style with
4636        | RErr -> ()
4637        | RConstString _ | RConstOptString _ ->
4638            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4639        | RInt _ | RInt64 _
4640        | RBool _ | RString _ | RStringList _
4641        | RStruct _ | RStructList _
4642        | RHashtable _ | RBufferOut _ ->
4643            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4644            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4645            pr "    return;\n";
4646            pr "  }\n";
4647       );
4648
4649       pr " done:\n";
4650       pr "  ctx->cb_sequence = 1;\n";
4651       pr "}\n\n";
4652
4653       (* Generate the action stub. *)
4654       generate_prototype ~extern:false ~semicolon:false ~newline:true
4655         ~handle:"g" name style;
4656
4657       let error_code =
4658         match fst style with
4659         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4660         | RConstString _ | RConstOptString _ ->
4661             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4662         | RString _ | RStringList _
4663         | RStruct _ | RStructList _
4664         | RHashtable _ | RBufferOut _ ->
4665             "NULL" in
4666
4667       pr "{\n";
4668
4669       (match snd style with
4670        | [] -> ()
4671        | _ -> pr "  struct %s_args args;\n" name
4672       );
4673
4674       pr "  struct %s_ctx ctx;\n" shortname;
4675       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4676       pr "  int serial;\n";
4677       pr "\n";
4678       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4679       pr "  guestfs_set_busy (g);\n";
4680       pr "\n";
4681       pr "  memset (&ctx, 0, sizeof ctx);\n";
4682       pr "\n";
4683
4684       (* Send the main header and arguments. *)
4685       (match snd style with
4686        | [] ->
4687            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4688              (String.uppercase shortname)
4689        | args ->
4690            List.iter (
4691              function
4692              | Pathname n | Device n | Dev_or_Path n | String n ->
4693                  pr "  args.%s = (char *) %s;\n" n n
4694              | OptString n ->
4695                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4696              | StringList n ->
4697                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4698                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4699              | Bool n ->
4700                  pr "  args.%s = %s;\n" n n
4701              | Int n ->
4702                  pr "  args.%s = %s;\n" n n
4703              | FileIn _ | FileOut _ -> ()
4704            ) args;
4705            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4706              (String.uppercase shortname);
4707            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4708              name;
4709       );
4710       pr "  if (serial == -1) {\n";
4711       pr "    guestfs_end_busy (g);\n";
4712       pr "    return %s;\n" error_code;
4713       pr "  }\n";
4714       pr "\n";
4715
4716       (* Send any additional files (FileIn) requested. *)
4717       let need_read_reply_label = ref false in
4718       List.iter (
4719         function
4720         | FileIn n ->
4721             pr "  {\n";
4722             pr "    int r;\n";
4723             pr "\n";
4724             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4725             pr "    if (r == -1) {\n";
4726             pr "      guestfs_end_busy (g);\n";
4727             pr "      return %s;\n" error_code;
4728             pr "    }\n";
4729             pr "    if (r == -2) /* daemon cancelled */\n";
4730             pr "      goto read_reply;\n";
4731             need_read_reply_label := true;
4732             pr "  }\n";
4733             pr "\n";
4734         | _ -> ()
4735       ) (snd style);
4736
4737       (* Wait for the reply from the remote end. *)
4738       if !need_read_reply_label then pr " read_reply:\n";
4739       pr "  guestfs__switch_to_receiving (g);\n";
4740       pr "  ctx.cb_sequence = 0;\n";
4741       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4742       pr "  (void) ml->main_loop_run (ml, g);\n";
4743       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4744       pr "  if (ctx.cb_sequence != 1) {\n";
4745       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4746       pr "    guestfs_end_busy (g);\n";
4747       pr "    return %s;\n" error_code;
4748       pr "  }\n";
4749       pr "\n";
4750
4751       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4752         (String.uppercase shortname);
4753       pr "    guestfs_end_busy (g);\n";
4754       pr "    return %s;\n" error_code;
4755       pr "  }\n";
4756       pr "\n";
4757
4758       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4759       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4760       pr "    free (ctx.err.error_message);\n";
4761       pr "    guestfs_end_busy (g);\n";
4762       pr "    return %s;\n" error_code;
4763       pr "  }\n";
4764       pr "\n";
4765
4766       (* Expecting to receive further files (FileOut)? *)
4767       List.iter (
4768         function
4769         | FileOut n ->
4770             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4771             pr "    guestfs_end_busy (g);\n";
4772             pr "    return %s;\n" error_code;
4773             pr "  }\n";
4774             pr "\n";
4775         | _ -> ()
4776       ) (snd style);
4777
4778       pr "  guestfs_end_busy (g);\n";
4779
4780       (match fst style with
4781        | RErr -> pr "  return 0;\n"
4782        | RInt n | RInt64 n | RBool n ->
4783            pr "  return ctx.ret.%s;\n" n
4784        | RConstString _ | RConstOptString _ ->
4785            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4786        | RString n ->
4787            pr "  return ctx.ret.%s; /* caller will free */\n" n
4788        | RStringList n | RHashtable n ->
4789            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4790            pr "  ctx.ret.%s.%s_val =\n" n n;
4791            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4792            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4793              n n;
4794            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4795            pr "  return ctx.ret.%s.%s_val;\n" n n
4796        | RStruct (n, _) ->
4797            pr "  /* caller will free this */\n";
4798            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4799        | RStructList (n, _) ->
4800            pr "  /* caller will free this */\n";
4801            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4802        | RBufferOut n ->
4803            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4804            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4805       );
4806
4807       pr "}\n\n"
4808   ) daemon_functions;
4809
4810   (* Functions to free structures. *)
4811   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4812   pr " * structure format is identical to the XDR format.  See note in\n";
4813   pr " * generator.ml.\n";
4814   pr " */\n";
4815   pr "\n";
4816
4817   List.iter (
4818     fun (typ, _) ->
4819       pr "void\n";
4820       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4821       pr "{\n";
4822       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4823       pr "  free (x);\n";
4824       pr "}\n";
4825       pr "\n";
4826
4827       pr "void\n";
4828       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4829       pr "{\n";
4830       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4831       pr "  free (x);\n";
4832       pr "}\n";
4833       pr "\n";
4834
4835   ) structs;
4836
4837 (* Generate daemon/actions.h. *)
4838 and generate_daemon_actions_h () =
4839   generate_header CStyle GPLv2;
4840
4841   pr "#include \"../src/guestfs_protocol.h\"\n";
4842   pr "\n";
4843
4844   List.iter (
4845     fun (name, style, _, _, _, _, _) ->
4846       generate_prototype
4847         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4848         name style;
4849   ) daemon_functions
4850
4851 (* Generate the server-side stubs. *)
4852 and generate_daemon_actions () =
4853   generate_header CStyle GPLv2;
4854
4855   pr "#include <config.h>\n";
4856   pr "\n";
4857   pr "#include <stdio.h>\n";
4858   pr "#include <stdlib.h>\n";
4859   pr "#include <string.h>\n";
4860   pr "#include <inttypes.h>\n";
4861   pr "#include <ctype.h>\n";
4862   pr "#include <rpc/types.h>\n";
4863   pr "#include <rpc/xdr.h>\n";
4864   pr "\n";
4865   pr "#include \"daemon.h\"\n";
4866   pr "#include \"../src/guestfs_protocol.h\"\n";
4867   pr "#include \"actions.h\"\n";
4868   pr "\n";
4869
4870   List.iter (
4871     fun (name, style, _, _, _, _, _) ->
4872       (* Generate server-side stubs. *)
4873       pr "static void %s_stub (XDR *xdr_in)\n" name;
4874       pr "{\n";
4875       let error_code =
4876         match fst style with
4877         | RErr | RInt _ -> pr "  int r;\n"; "-1"
4878         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
4879         | RBool _ -> pr "  int r;\n"; "-1"
4880         | RConstString _ | RConstOptString _ ->
4881             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4882         | RString _ -> pr "  char *r;\n"; "NULL"
4883         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
4884         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
4885         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
4886         | RBufferOut _ ->
4887             pr "  size_t size;\n";
4888             pr "  char *r;\n";
4889             "NULL" in
4890
4891       (match snd style with
4892        | [] -> ()
4893        | args ->
4894            pr "  struct guestfs_%s_args args;\n" name;
4895            List.iter (
4896              function
4897              | Device n | Dev_or_Path n
4898              | Pathname n
4899              | String n -> ()
4900              | OptString n -> pr "  char *%s;\n" n
4901              | StringList n -> pr "  char **%s;\n" n
4902              | Bool n -> pr "  int %s;\n" n
4903              | Int n -> pr "  int %s;\n" n
4904              | FileIn _ | FileOut _ -> ()
4905            ) args
4906       );
4907       pr "\n";
4908
4909       (match snd style with
4910        | [] -> ()
4911        | args ->
4912            pr "  memset (&args, 0, sizeof args);\n";
4913            pr "\n";
4914            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4915            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4916            pr "    return;\n";
4917            pr "  }\n";
4918            let pr_args n =
4919              pr "  char *%s = args.%s;\n" n n
4920            in
4921            List.iter (
4922              function
4923              | Pathname n ->
4924                  pr_args n;
4925                  pr "  ABS_PATH (%s, goto done);\n" n;
4926              | Device n ->
4927                  pr_args n;
4928                  pr "  RESOLVE_DEVICE (%s, goto done);" n;
4929              | Dev_or_Path n ->
4930                  pr_args n;
4931                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);" n;
4932              | String n -> pr_args n
4933              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
4934              | StringList n ->
4935                  pr "  %s = realloc (args.%s.%s_val,\n" n n n;
4936                  pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4937                  pr "  if (%s == NULL) {\n" n;
4938                  pr "    reply_with_perror (\"realloc\");\n";
4939                  pr "    goto done;\n";
4940                  pr "  }\n";
4941                  pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
4942                  pr "  args.%s.%s_val = %s;\n" n n n;
4943              | Bool n -> pr "  %s = args.%s;\n" n n
4944              | Int n -> pr "  %s = args.%s;\n" n n
4945              | FileIn _ | FileOut _ -> ()
4946            ) args;
4947            pr "\n"
4948       );
4949
4950       (* this is used at least for do_equal *)
4951       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
4952         (* Emit NEED_ROOT just once, even when there are two or
4953            more Pathname args *)
4954         pr "  NEED_ROOT (goto done);\n";
4955       );
4956
4957       (* Don't want to call the impl with any FileIn or FileOut
4958        * parameters, since these go "outside" the RPC protocol.
4959        *)
4960       let args' =
4961         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
4962           (snd style) in
4963       pr "  r = do_%s " name;
4964       generate_c_call_args (fst style, args');
4965       pr ";\n";
4966
4967       pr "  if (r == %s)\n" error_code;
4968       pr "    /* do_%s has already called reply_with_error */\n" name;
4969       pr "    goto done;\n";
4970       pr "\n";
4971
4972       (* If there are any FileOut parameters, then the impl must
4973        * send its own reply.
4974        *)
4975       let no_reply =
4976         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
4977       if no_reply then
4978         pr "  /* do_%s has already sent a reply */\n" name
4979       else (
4980         match fst style with
4981         | RErr -> pr "  reply (NULL, NULL);\n"
4982         | RInt n | RInt64 n | RBool n ->
4983             pr "  struct guestfs_%s_ret ret;\n" name;
4984             pr "  ret.%s = r;\n" n;
4985             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4986               name
4987         | RConstString _ | RConstOptString _ ->
4988             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4989         | RString n ->
4990             pr "  struct guestfs_%s_ret ret;\n" name;
4991             pr "  ret.%s = r;\n" n;
4992             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4993               name;
4994             pr "  free (r);\n"
4995         | RStringList n | RHashtable n ->
4996             pr "  struct guestfs_%s_ret ret;\n" name;
4997             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
4998             pr "  ret.%s.%s_val = r;\n" n n;
4999             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5000               name;
5001             pr "  free_strings (r);\n"
5002         | RStruct (n, _) ->
5003             pr "  struct guestfs_%s_ret ret;\n" name;
5004             pr "  ret.%s = *r;\n" n;
5005             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5006               name;
5007             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5008               name
5009         | RStructList (n, _) ->
5010             pr "  struct guestfs_%s_ret ret;\n" name;
5011             pr "  ret.%s = *r;\n" n;
5012             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5013               name;
5014             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5015               name
5016         | RBufferOut n ->
5017             pr "  struct guestfs_%s_ret ret;\n" name;
5018             pr "  ret.%s.%s_val = r;\n" n n;
5019             pr "  ret.%s.%s_len = size;\n" n n;
5020             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5021               name;
5022             pr "  free (r);\n"
5023       );
5024
5025       (* Free the args. *)
5026       (match snd style with
5027        | [] ->
5028            pr "done: ;\n";
5029        | _ ->
5030            pr "done:\n";
5031            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5032              name
5033       );
5034
5035       pr "}\n\n";
5036   ) daemon_functions;
5037
5038   (* Dispatch function. *)
5039   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5040   pr "{\n";
5041   pr "  switch (proc_nr) {\n";
5042
5043   List.iter (
5044     fun (name, style, _, _, _, _, _) ->
5045       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5046       pr "      %s_stub (xdr_in);\n" name;
5047       pr "      break;\n"
5048   ) daemon_functions;
5049
5050   pr "    default:\n";
5051   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory\", proc_nr);\n";
5052   pr "  }\n";
5053   pr "}\n";
5054   pr "\n";
5055
5056   (* LVM columns and tokenization functions. *)
5057   (* XXX This generates crap code.  We should rethink how we
5058    * do this parsing.
5059    *)
5060   List.iter (
5061     function
5062     | typ, cols ->
5063         pr "static const char *lvm_%s_cols = \"%s\";\n"
5064           typ (String.concat "," (List.map fst cols));
5065         pr "\n";
5066
5067         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5068         pr "{\n";
5069         pr "  char *tok, *p, *next;\n";
5070         pr "  int i, j;\n";
5071         pr "\n";
5072         (*
5073           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5074           pr "\n";
5075         *)
5076         pr "  if (!str) {\n";
5077         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5078         pr "    return -1;\n";
5079         pr "  }\n";
5080         pr "  if (!*str || isspace (*str)) {\n";
5081         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5082         pr "    return -1;\n";
5083         pr "  }\n";
5084         pr "  tok = str;\n";
5085         List.iter (
5086           fun (name, coltype) ->
5087             pr "  if (!tok) {\n";
5088             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5089             pr "    return -1;\n";
5090             pr "  }\n";
5091             pr "  p = strchrnul (tok, ',');\n";
5092             pr "  if (*p) next = p+1; else next = NULL;\n";
5093             pr "  *p = '\\0';\n";
5094             (match coltype with
5095              | FString ->
5096                  pr "  r->%s = strdup (tok);\n" name;
5097                  pr "  if (r->%s == NULL) {\n" name;
5098                  pr "    perror (\"strdup\");\n";
5099                  pr "    return -1;\n";
5100                  pr "  }\n"
5101              | FUUID ->
5102                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5103                  pr "    if (tok[j] == '\\0') {\n";
5104                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5105                  pr "      return -1;\n";
5106                  pr "    } else if (tok[j] != '-')\n";
5107                  pr "      r->%s[i++] = tok[j];\n" name;
5108                  pr "  }\n";
5109              | FBytes ->
5110                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5111                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5112                  pr "    return -1;\n";
5113                  pr "  }\n";
5114              | FInt64 ->
5115                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5116                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5117                  pr "    return -1;\n";
5118                  pr "  }\n";
5119              | FOptPercent ->
5120                  pr "  if (tok[0] == '\\0')\n";
5121                  pr "    r->%s = -1;\n" name;
5122                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5123                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5124                  pr "    return -1;\n";
5125                  pr "  }\n";
5126              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5127                  assert false (* can never be an LVM column *)
5128             );
5129             pr "  tok = next;\n";
5130         ) cols;
5131
5132         pr "  if (tok != NULL) {\n";
5133         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5134         pr "    return -1;\n";
5135         pr "  }\n";
5136         pr "  return 0;\n";
5137         pr "}\n";
5138         pr "\n";
5139
5140         pr "guestfs_int_lvm_%s_list *\n" typ;
5141         pr "parse_command_line_%ss (void)\n" typ;
5142         pr "{\n";
5143         pr "  char *out, *err;\n";
5144         pr "  char *p, *pend;\n";
5145         pr "  int r, i;\n";
5146         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5147         pr "  void *newp;\n";
5148         pr "\n";
5149         pr "  ret = malloc (sizeof *ret);\n";
5150         pr "  if (!ret) {\n";
5151         pr "    reply_with_perror (\"malloc\");\n";
5152         pr "    return NULL;\n";
5153         pr "  }\n";
5154         pr "\n";
5155         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5156         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5157         pr "\n";
5158         pr "  r = command (&out, &err,\n";
5159         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5160         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5161         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5162         pr "  if (r == -1) {\n";
5163         pr "    reply_with_error (\"%%s\", err);\n";
5164         pr "    free (out);\n";
5165         pr "    free (err);\n";
5166         pr "    free (ret);\n";
5167         pr "    return NULL;\n";
5168         pr "  }\n";
5169         pr "\n";
5170         pr "  free (err);\n";
5171         pr "\n";
5172         pr "  /* Tokenize each line of the output. */\n";
5173         pr "  p = out;\n";
5174         pr "  i = 0;\n";
5175         pr "  while (p) {\n";
5176         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5177         pr "    if (pend) {\n";
5178         pr "      *pend = '\\0';\n";
5179         pr "      pend++;\n";
5180         pr "    }\n";
5181         pr "\n";
5182         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5183         pr "      p++;\n";
5184         pr "\n";
5185         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5186         pr "      p = pend;\n";
5187         pr "      continue;\n";
5188         pr "    }\n";
5189         pr "\n";
5190         pr "    /* Allocate some space to store this next entry. */\n";
5191         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5192         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5193         pr "    if (newp == NULL) {\n";
5194         pr "      reply_with_perror (\"realloc\");\n";
5195         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5196         pr "      free (ret);\n";
5197         pr "      free (out);\n";
5198         pr "      return NULL;\n";
5199         pr "    }\n";
5200         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5201         pr "\n";
5202         pr "    /* Tokenize the next entry. */\n";
5203         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5204         pr "    if (r == -1) {\n";
5205         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5206         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5207         pr "      free (ret);\n";
5208         pr "      free (out);\n";
5209         pr "      return NULL;\n";
5210         pr "    }\n";
5211         pr "\n";
5212         pr "    ++i;\n";
5213         pr "    p = pend;\n";
5214         pr "  }\n";
5215         pr "\n";
5216         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5217         pr "\n";
5218         pr "  free (out);\n";
5219         pr "  return ret;\n";
5220         pr "}\n"
5221
5222   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5223
5224 (* Generate a list of function names, for debugging in the daemon.. *)
5225 and generate_daemon_names () =
5226   generate_header CStyle GPLv2;
5227
5228   pr "#include <config.h>\n";
5229   pr "\n";
5230   pr "#include \"daemon.h\"\n";
5231   pr "\n";
5232
5233   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5234   pr "const char *function_names[] = {\n";
5235   List.iter (
5236     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5237   ) daemon_functions;
5238   pr "};\n";
5239
5240 (* Generate the tests. *)
5241 and generate_tests () =
5242   generate_header CStyle GPLv2;
5243
5244   pr "\
5245 #include <stdio.h>
5246 #include <stdlib.h>
5247 #include <string.h>
5248 #include <unistd.h>
5249 #include <sys/types.h>
5250 #include <fcntl.h>
5251
5252 #include \"guestfs.h\"
5253
5254 static guestfs_h *g;
5255 static int suppress_error = 0;
5256
5257 static void print_error (guestfs_h *g, void *data, const char *msg)
5258 {
5259   if (!suppress_error)
5260     fprintf (stderr, \"%%s\\n\", msg);
5261 }
5262
5263 static void print_strings (char * const * const argv)
5264 {
5265   int argc;
5266
5267   for (argc = 0; argv[argc] != NULL; ++argc)
5268     printf (\"\\t%%s\\n\", argv[argc]);
5269 }
5270
5271 /*
5272 static void print_table (char * const * const argv)
5273 {
5274   int i;
5275
5276   for (i = 0; argv[i] != NULL; i += 2)
5277     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5278 }
5279 */
5280
5281 ";
5282
5283   (* Generate a list of commands which are not tested anywhere. *)
5284   pr "static void no_test_warnings (void)\n";
5285   pr "{\n";
5286
5287   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5288   List.iter (
5289     fun (_, _, _, _, tests, _, _) ->
5290       let tests = filter_map (
5291         function
5292         | (_, (Always|If _|Unless _), test) -> Some test
5293         | (_, Disabled, _) -> None
5294       ) tests in
5295       let seq = List.concat (List.map seq_of_test tests) in
5296       let cmds_tested = List.map List.hd seq in
5297       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5298   ) all_functions;
5299
5300   List.iter (
5301     fun (name, _, _, _, _, _, _) ->
5302       if not (Hashtbl.mem hash name) then
5303         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5304   ) all_functions;
5305
5306   pr "}\n";
5307   pr "\n";
5308
5309   (* Generate the actual tests.  Note that we generate the tests
5310    * in reverse order, deliberately, so that (in general) the
5311    * newest tests run first.  This makes it quicker and easier to
5312    * debug them.
5313    *)
5314   let test_names =
5315     List.map (
5316       fun (name, _, _, _, tests, _, _) ->
5317         mapi (generate_one_test name) tests
5318     ) (List.rev all_functions) in
5319   let test_names = List.concat test_names in
5320   let nr_tests = List.length test_names in
5321
5322   pr "\
5323 int main (int argc, char *argv[])
5324 {
5325   char c = 0;
5326   int failed = 0;
5327   const char *filename;
5328   int fd;
5329   int nr_tests, test_num = 0;
5330
5331   setbuf (stdout, NULL);
5332
5333   no_test_warnings ();
5334
5335   g = guestfs_create ();
5336   if (g == NULL) {
5337     printf (\"guestfs_create FAILED\\n\");
5338     exit (1);
5339   }
5340
5341   guestfs_set_error_handler (g, print_error, NULL);
5342
5343   guestfs_set_path (g, \"../appliance\");
5344
5345   filename = \"test1.img\";
5346   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5347   if (fd == -1) {
5348     perror (filename);
5349     exit (1);
5350   }
5351   if (lseek (fd, %d, SEEK_SET) == -1) {
5352     perror (\"lseek\");
5353     close (fd);
5354     unlink (filename);
5355     exit (1);
5356   }
5357   if (write (fd, &c, 1) == -1) {
5358     perror (\"write\");
5359     close (fd);
5360     unlink (filename);
5361     exit (1);
5362   }
5363   if (close (fd) == -1) {
5364     perror (filename);
5365     unlink (filename);
5366     exit (1);
5367   }
5368   if (guestfs_add_drive (g, filename) == -1) {
5369     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5370     exit (1);
5371   }
5372
5373   filename = \"test2.img\";
5374   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5375   if (fd == -1) {
5376     perror (filename);
5377     exit (1);
5378   }
5379   if (lseek (fd, %d, SEEK_SET) == -1) {
5380     perror (\"lseek\");
5381     close (fd);
5382     unlink (filename);
5383     exit (1);
5384   }
5385   if (write (fd, &c, 1) == -1) {
5386     perror (\"write\");
5387     close (fd);
5388     unlink (filename);
5389     exit (1);
5390   }
5391   if (close (fd) == -1) {
5392     perror (filename);
5393     unlink (filename);
5394     exit (1);
5395   }
5396   if (guestfs_add_drive (g, filename) == -1) {
5397     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5398     exit (1);
5399   }
5400
5401   filename = \"test3.img\";
5402   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5403   if (fd == -1) {
5404     perror (filename);
5405     exit (1);
5406   }
5407   if (lseek (fd, %d, SEEK_SET) == -1) {
5408     perror (\"lseek\");
5409     close (fd);
5410     unlink (filename);
5411     exit (1);
5412   }
5413   if (write (fd, &c, 1) == -1) {
5414     perror (\"write\");
5415     close (fd);
5416     unlink (filename);
5417     exit (1);
5418   }
5419   if (close (fd) == -1) {
5420     perror (filename);
5421     unlink (filename);
5422     exit (1);
5423   }
5424   if (guestfs_add_drive (g, filename) == -1) {
5425     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5426     exit (1);
5427   }
5428
5429   if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
5430     printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
5431     exit (1);
5432   }
5433
5434   if (guestfs_launch (g) == -1) {
5435     printf (\"guestfs_launch FAILED\\n\");
5436     exit (1);
5437   }
5438
5439   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5440   alarm (600);
5441
5442   if (guestfs_wait_ready (g) == -1) {
5443     printf (\"guestfs_wait_ready FAILED\\n\");
5444     exit (1);
5445   }
5446
5447   /* Cancel previous alarm. */
5448   alarm (0);
5449
5450   nr_tests = %d;
5451
5452 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5453
5454   iteri (
5455     fun i test_name ->
5456       pr "  test_num++;\n";
5457       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5458       pr "  if (%s () == -1) {\n" test_name;
5459       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5460       pr "    failed++;\n";
5461       pr "  }\n";
5462   ) test_names;
5463   pr "\n";
5464
5465   pr "  guestfs_close (g);\n";
5466   pr "  unlink (\"test1.img\");\n";
5467   pr "  unlink (\"test2.img\");\n";
5468   pr "  unlink (\"test3.img\");\n";
5469   pr "\n";
5470
5471   pr "  if (failed > 0) {\n";
5472   pr "    printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
5473   pr "    exit (1);\n";
5474   pr "  }\n";
5475   pr "\n";
5476
5477   pr "  exit (0);\n";
5478   pr "}\n"
5479
5480 and generate_one_test name i (init, prereq, test) =
5481   let test_name = sprintf "test_%s_%d" name i in
5482
5483   pr "\
5484 static int %s_skip (void)
5485 {
5486   const char *str;
5487
5488   str = getenv (\"TEST_ONLY\");
5489   if (str)
5490     return strstr (str, \"%s\") == NULL;
5491   str = getenv (\"SKIP_%s\");
5492   if (str && strcmp (str, \"1\") == 0) return 1;
5493   str = getenv (\"SKIP_TEST_%s\");
5494   if (str && strcmp (str, \"1\") == 0) return 1;
5495   return 0;
5496 }
5497
5498 " test_name name (String.uppercase test_name) (String.uppercase name);
5499
5500   (match prereq with
5501    | Disabled | Always -> ()
5502    | If code | Unless code ->
5503        pr "static int %s_prereq (void)\n" test_name;
5504        pr "{\n";
5505        pr "  %s\n" code;
5506        pr "}\n";
5507        pr "\n";
5508   );
5509
5510   pr "\
5511 static int %s (void)
5512 {
5513   if (%s_skip ()) {
5514     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5515     return 0;
5516   }
5517
5518 " test_name test_name test_name;
5519
5520   (match prereq with
5521    | Disabled ->
5522        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5523    | If _ ->
5524        pr "  if (! %s_prereq ()) {\n" test_name;
5525        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5526        pr "    return 0;\n";
5527        pr "  }\n";
5528        pr "\n";
5529        generate_one_test_body name i test_name init test;
5530    | Unless _ ->
5531        pr "  if (%s_prereq ()) {\n" test_name;
5532        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5533        pr "    return 0;\n";
5534        pr "  }\n";
5535        pr "\n";
5536        generate_one_test_body name i test_name init test;
5537    | Always ->
5538        generate_one_test_body name i test_name init test
5539   );
5540
5541   pr "  return 0;\n";
5542   pr "}\n";
5543   pr "\n";
5544   test_name
5545
5546 and generate_one_test_body name i test_name init test =
5547   (match init with
5548    | InitNone (* XXX at some point, InitNone and InitEmpty became
5549                * folded together as the same thing.  Really we should
5550                * make InitNone do nothing at all, but the tests may
5551                * need to be checked to make sure this is OK.
5552                *)
5553    | InitEmpty ->
5554        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5555        List.iter (generate_test_command_call test_name)
5556          [["blockdev_setrw"; "/dev/sda"];
5557           ["umount_all"];
5558           ["lvm_remove_all"]]
5559    | InitPartition ->
5560        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5561        List.iter (generate_test_command_call test_name)
5562          [["blockdev_setrw"; "/dev/sda"];
5563           ["umount_all"];
5564           ["lvm_remove_all"];
5565           ["sfdiskM"; "/dev/sda"; ","]]
5566    | InitBasicFS ->
5567        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5568        List.iter (generate_test_command_call test_name)
5569          [["blockdev_setrw"; "/dev/sda"];
5570           ["umount_all"];
5571           ["lvm_remove_all"];
5572           ["sfdiskM"; "/dev/sda"; ","];
5573           ["mkfs"; "ext2"; "/dev/sda1"];
5574           ["mount"; "/dev/sda1"; "/"]]
5575    | InitBasicFSonLVM ->
5576        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5577          test_name;
5578        List.iter (generate_test_command_call test_name)
5579          [["blockdev_setrw"; "/dev/sda"];
5580           ["umount_all"];
5581           ["lvm_remove_all"];
5582           ["sfdiskM"; "/dev/sda"; ","];
5583           ["pvcreate"; "/dev/sda1"];
5584           ["vgcreate"; "VG"; "/dev/sda1"];
5585           ["lvcreate"; "LV"; "VG"; "8"];
5586           ["mkfs"; "ext2"; "/dev/VG/LV"];
5587           ["mount"; "/dev/VG/LV"; "/"]]
5588    | InitSquashFS ->
5589        pr "  /* InitSquashFS for %s */\n" test_name;
5590        List.iter (generate_test_command_call test_name)
5591          [["blockdev_setrw"; "/dev/sda"];
5592           ["umount_all"];
5593           ["lvm_remove_all"];
5594           ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
5595   );
5596
5597   let get_seq_last = function
5598     | [] ->
5599         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5600           test_name
5601     | seq ->
5602         let seq = List.rev seq in
5603         List.rev (List.tl seq), List.hd seq
5604   in
5605
5606   match test with
5607   | TestRun seq ->
5608       pr "  /* TestRun for %s (%d) */\n" name i;
5609       List.iter (generate_test_command_call test_name) seq
5610   | TestOutput (seq, expected) ->
5611       pr "  /* TestOutput for %s (%d) */\n" name i;
5612       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5613       let seq, last = get_seq_last seq in
5614       let test () =
5615         pr "    if (strcmp (r, expected) != 0) {\n";
5616         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5617         pr "      return -1;\n";
5618         pr "    }\n"
5619       in
5620       List.iter (generate_test_command_call test_name) seq;
5621       generate_test_command_call ~test test_name last
5622   | TestOutputList (seq, expected) ->
5623       pr "  /* TestOutputList for %s (%d) */\n" name i;
5624       let seq, last = get_seq_last seq in
5625       let test () =
5626         iteri (
5627           fun i str ->
5628             pr "    if (!r[%d]) {\n" i;
5629             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5630             pr "      print_strings (r);\n";
5631             pr "      return -1;\n";
5632             pr "    }\n";
5633             pr "    {\n";
5634             pr "      const char *expected = \"%s\";\n" (c_quote str);
5635             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5636             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5637             pr "        return -1;\n";
5638             pr "      }\n";
5639             pr "    }\n"
5640         ) expected;
5641         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5642         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5643           test_name;
5644         pr "      print_strings (r);\n";
5645         pr "      return -1;\n";
5646         pr "    }\n"
5647       in
5648       List.iter (generate_test_command_call test_name) seq;
5649       generate_test_command_call ~test test_name last
5650   | TestOutputListOfDevices (seq, expected) ->
5651       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5652       let seq, last = get_seq_last seq in
5653       let test () =
5654         iteri (
5655           fun i str ->
5656             pr "    if (!r[%d]) {\n" i;
5657             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5658             pr "      print_strings (r);\n";
5659             pr "      return -1;\n";
5660             pr "    }\n";
5661             pr "    {\n";
5662             pr "      const char *expected = \"%s\";\n" (c_quote str);
5663             pr "      r[%d][5] = 's';\n" i;
5664             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5665             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5666             pr "        return -1;\n";
5667             pr "      }\n";
5668             pr "    }\n"
5669         ) expected;
5670         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5671         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5672           test_name;
5673         pr "      print_strings (r);\n";
5674         pr "      return -1;\n";
5675         pr "    }\n"
5676       in
5677       List.iter (generate_test_command_call test_name) seq;
5678       generate_test_command_call ~test test_name last
5679   | TestOutputInt (seq, expected) ->
5680       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5681       let seq, last = get_seq_last seq in
5682       let test () =
5683         pr "    if (r != %d) {\n" expected;
5684         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5685           test_name expected;
5686         pr "               (int) r);\n";
5687         pr "      return -1;\n";
5688         pr "    }\n"
5689       in
5690       List.iter (generate_test_command_call test_name) seq;
5691       generate_test_command_call ~test test_name last
5692   | TestOutputIntOp (seq, op, expected) ->
5693       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5694       let seq, last = get_seq_last seq in
5695       let test () =
5696         pr "    if (! (r %s %d)) {\n" op expected;
5697         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5698           test_name op expected;
5699         pr "               (int) r);\n";
5700         pr "      return -1;\n";
5701         pr "    }\n"
5702       in
5703       List.iter (generate_test_command_call test_name) seq;
5704       generate_test_command_call ~test test_name last
5705   | TestOutputTrue seq ->
5706       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5707       let seq, last = get_seq_last seq in
5708       let test () =
5709         pr "    if (!r) {\n";
5710         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5711           test_name;
5712         pr "      return -1;\n";
5713         pr "    }\n"
5714       in
5715       List.iter (generate_test_command_call test_name) seq;
5716       generate_test_command_call ~test test_name last
5717   | TestOutputFalse seq ->
5718       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5719       let seq, last = get_seq_last seq in
5720       let test () =
5721         pr "    if (r) {\n";
5722         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5723           test_name;
5724         pr "      return -1;\n";
5725         pr "    }\n"
5726       in
5727       List.iter (generate_test_command_call test_name) seq;
5728       generate_test_command_call ~test test_name last
5729   | TestOutputLength (seq, expected) ->
5730       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5731       let seq, last = get_seq_last seq in
5732       let test () =
5733         pr "    int j;\n";
5734         pr "    for (j = 0; j < %d; ++j)\n" expected;
5735         pr "      if (r[j] == NULL) {\n";
5736         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5737           test_name;
5738         pr "        print_strings (r);\n";
5739         pr "        return -1;\n";
5740         pr "      }\n";
5741         pr "    if (r[j] != NULL) {\n";
5742         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5743           test_name;
5744         pr "      print_strings (r);\n";
5745         pr "      return -1;\n";
5746         pr "    }\n"
5747       in
5748       List.iter (generate_test_command_call test_name) seq;
5749       generate_test_command_call ~test test_name last
5750   | TestOutputBuffer (seq, expected) ->
5751       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5752       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5753       let seq, last = get_seq_last seq in
5754       let len = String.length expected in
5755       let test () =
5756         pr "    if (size != %d) {\n" len;
5757         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5758         pr "      return -1;\n";
5759         pr "    }\n";
5760         pr "    if (strncmp (r, expected, size) != 0) {\n";
5761         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5762         pr "      return -1;\n";
5763         pr "    }\n"
5764       in
5765       List.iter (generate_test_command_call test_name) seq;
5766       generate_test_command_call ~test test_name last
5767   | TestOutputStruct (seq, checks) ->
5768       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5769       let seq, last = get_seq_last seq in
5770       let test () =
5771         List.iter (
5772           function
5773           | CompareWithInt (field, expected) ->
5774               pr "    if (r->%s != %d) {\n" field expected;
5775               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5776                 test_name field expected;
5777               pr "               (int) r->%s);\n" field;
5778               pr "      return -1;\n";
5779               pr "    }\n"
5780           | CompareWithIntOp (field, op, expected) ->
5781               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5782               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5783                 test_name field op expected;
5784               pr "               (int) r->%s);\n" field;
5785               pr "      return -1;\n";
5786               pr "    }\n"
5787           | CompareWithString (field, expected) ->
5788               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5789               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5790                 test_name field expected;
5791               pr "               r->%s);\n" field;
5792               pr "      return -1;\n";
5793               pr "    }\n"
5794           | CompareFieldsIntEq (field1, field2) ->
5795               pr "    if (r->%s != r->%s) {\n" field1 field2;
5796               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5797                 test_name field1 field2;
5798               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5799               pr "      return -1;\n";
5800               pr "    }\n"
5801           | CompareFieldsStrEq (field1, field2) ->
5802               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5803               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5804                 test_name field1 field2;
5805               pr "               r->%s, r->%s);\n" field1 field2;
5806               pr "      return -1;\n";
5807               pr "    }\n"
5808         ) checks
5809       in
5810       List.iter (generate_test_command_call test_name) seq;
5811       generate_test_command_call ~test test_name last
5812   | TestLastFail seq ->
5813       pr "  /* TestLastFail for %s (%d) */\n" name i;
5814       let seq, last = get_seq_last seq in
5815       List.iter (generate_test_command_call test_name) seq;
5816       generate_test_command_call test_name ~expect_error:true last
5817
5818 (* Generate the code to run a command, leaving the result in 'r'.
5819  * If you expect to get an error then you should set expect_error:true.
5820  *)
5821 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5822   match cmd with
5823   | [] -> assert false
5824   | name :: args ->
5825       (* Look up the command to find out what args/ret it has. *)
5826       let style =
5827         try
5828           let _, style, _, _, _, _, _ =
5829             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5830           style
5831         with Not_found ->
5832           failwithf "%s: in test, command %s was not found" test_name name in
5833
5834       if List.length (snd style) <> List.length args then
5835         failwithf "%s: in test, wrong number of args given to %s"
5836           test_name name;
5837
5838       pr "  {\n";
5839
5840       List.iter (
5841         function
5842         | OptString n, "NULL" -> ()
5843         | Pathname n, arg
5844         | Device n, arg
5845         | Dev_or_Path n, arg
5846         | String n, arg
5847         | OptString n, arg ->
5848             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
5849         | Int _, _
5850         | Bool _, _
5851         | FileIn _, _ | FileOut _, _ -> ()
5852         | StringList n, arg ->
5853             let strs = string_split " " arg in
5854             iteri (
5855               fun i str ->
5856                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
5857             ) strs;
5858             pr "    const char *%s[] = {\n" n;
5859             iteri (
5860               fun i _ -> pr "      %s_%d,\n" n i
5861             ) strs;
5862             pr "      NULL\n";
5863             pr "    };\n";
5864       ) (List.combine (snd style) args);
5865
5866       let error_code =
5867         match fst style with
5868         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
5869         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
5870         | RConstString _ | RConstOptString _ ->
5871             pr "    const char *r;\n"; "NULL"
5872         | RString _ -> pr "    char *r;\n"; "NULL"
5873         | RStringList _ | RHashtable _ ->
5874             pr "    char **r;\n";
5875             pr "    int i;\n";
5876             "NULL"
5877         | RStruct (_, typ) ->
5878             pr "    struct guestfs_%s *r;\n" typ; "NULL"
5879         | RStructList (_, typ) ->
5880             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
5881         | RBufferOut _ ->
5882             pr "    char *r;\n";
5883             pr "    size_t size;\n";
5884             "NULL" in
5885
5886       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
5887       pr "    r = guestfs_%s (g" name;
5888
5889       (* Generate the parameters. *)
5890       List.iter (
5891         function
5892         | OptString _, "NULL" -> pr ", NULL"
5893         | Pathname n, _
5894         | Device n, _ | Dev_or_Path n, _
5895         | String n, _
5896         | OptString n, _ ->
5897             pr ", %s" n
5898         | FileIn _, arg | FileOut _, arg ->
5899             pr ", \"%s\"" (c_quote arg)
5900         | StringList n, _ ->
5901             pr ", %s" n
5902         | Int _, arg ->
5903             let i =
5904               try int_of_string arg
5905               with Failure "int_of_string" ->
5906                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5907             pr ", %d" i
5908         | Bool _, arg ->
5909             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5910       ) (List.combine (snd style) args);
5911
5912       (match fst style with
5913        | RBufferOut _ -> pr ", &size"
5914        | _ -> ()
5915       );
5916
5917       pr ");\n";
5918
5919       if not expect_error then
5920         pr "    if (r == %s)\n" error_code
5921       else
5922         pr "    if (r != %s)\n" error_code;
5923       pr "      return -1;\n";
5924
5925       (* Insert the test code. *)
5926       (match test with
5927        | None -> ()
5928        | Some f -> f ()
5929       );
5930
5931       (match fst style with
5932        | RErr | RInt _ | RInt64 _ | RBool _
5933        | RConstString _ | RConstOptString _ -> ()
5934        | RString _ | RBufferOut _ -> pr "    free (r);\n"
5935        | RStringList _ | RHashtable _ ->
5936            pr "    for (i = 0; r[i] != NULL; ++i)\n";
5937            pr "      free (r[i]);\n";
5938            pr "    free (r);\n"
5939        | RStruct (_, typ) ->
5940            pr "    guestfs_free_%s (r);\n" typ
5941        | RStructList (_, typ) ->
5942            pr "    guestfs_free_%s_list (r);\n" typ
5943       );
5944
5945       pr "  }\n"
5946
5947 and c_quote str =
5948   let str = replace_str str "\r" "\\r" in
5949   let str = replace_str str "\n" "\\n" in
5950   let str = replace_str str "\t" "\\t" in
5951   let str = replace_str str "\000" "\\0" in
5952   str
5953
5954 (* Generate a lot of different functions for guestfish. *)
5955 and generate_fish_cmds () =
5956   generate_header CStyle GPLv2;
5957
5958   let all_functions =
5959     List.filter (
5960       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5961     ) all_functions in
5962   let all_functions_sorted =
5963     List.filter (
5964       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5965     ) all_functions_sorted in
5966
5967   pr "#include <stdio.h>\n";
5968   pr "#include <stdlib.h>\n";
5969   pr "#include <string.h>\n";
5970   pr "#include <inttypes.h>\n";
5971   pr "#include <ctype.h>\n";
5972   pr "\n";
5973   pr "#include <guestfs.h>\n";
5974   pr "#include \"fish.h\"\n";
5975   pr "\n";
5976
5977   (* list_commands function, which implements guestfish -h *)
5978   pr "void list_commands (void)\n";
5979   pr "{\n";
5980   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
5981   pr "  list_builtin_commands ();\n";
5982   List.iter (
5983     fun (name, _, _, flags, _, shortdesc, _) ->
5984       let name = replace_char name '_' '-' in
5985       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
5986         name shortdesc
5987   ) all_functions_sorted;
5988   pr "  printf (\"    %%s\\n\",";
5989   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
5990   pr "}\n";
5991   pr "\n";
5992
5993   (* display_command function, which implements guestfish -h cmd *)
5994   pr "void display_command (const char *cmd)\n";
5995   pr "{\n";
5996   List.iter (
5997     fun (name, style, _, flags, _, shortdesc, longdesc) ->
5998       let name2 = replace_char name '_' '-' in
5999       let alias =
6000         try find_map (function FishAlias n -> Some n | _ -> None) flags
6001         with Not_found -> name in
6002       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6003       let synopsis =
6004         match snd style with
6005         | [] -> name2
6006         | args ->
6007             sprintf "%s <%s>"
6008               name2 (String.concat "> <" (List.map name_of_argt args)) in
6009
6010       let warnings =
6011         if List.mem ProtocolLimitWarning flags then
6012           ("\n\n" ^ protocol_limit_warning)
6013         else "" in
6014
6015       (* For DangerWillRobinson commands, we should probably have
6016        * guestfish prompt before allowing you to use them (especially
6017        * in interactive mode). XXX
6018        *)
6019       let warnings =
6020         warnings ^
6021           if List.mem DangerWillRobinson flags then
6022             ("\n\n" ^ danger_will_robinson)
6023           else "" in
6024
6025       let warnings =
6026         warnings ^
6027           match deprecation_notice flags with
6028           | None -> ""
6029           | Some txt -> "\n\n" ^ txt in
6030
6031       let describe_alias =
6032         if name <> alias then
6033           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6034         else "" in
6035
6036       pr "  if (";
6037       pr "strcasecmp (cmd, \"%s\") == 0" name;
6038       if name <> name2 then
6039         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6040       if name <> alias then
6041         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6042       pr ")\n";
6043       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6044         name2 shortdesc
6045         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6046       pr "  else\n"
6047   ) all_functions;
6048   pr "    display_builtin_command (cmd);\n";
6049   pr "}\n";
6050   pr "\n";
6051
6052   (* print_* functions *)
6053   List.iter (
6054     fun (typ, cols) ->
6055       let needs_i =
6056         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6057
6058       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6059       pr "{\n";
6060       if needs_i then (
6061         pr "  int i;\n";
6062         pr "\n"
6063       );
6064       List.iter (
6065         function
6066         | name, FString ->
6067             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6068         | name, FUUID ->
6069             pr "  printf (\"%s: \");\n" name;
6070             pr "  for (i = 0; i < 32; ++i)\n";
6071             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6072             pr "  printf (\"\\n\");\n"
6073         | name, FBuffer ->
6074             pr "  printf (\"%%s%s: \", indent);\n" name;
6075             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6076             pr "    if (isprint (%s->%s[i]))\n" typ name;
6077             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6078             pr "    else\n";
6079             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6080             pr "  printf (\"\\n\");\n"
6081         | name, (FUInt64|FBytes) ->
6082             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6083               name typ name
6084         | name, FInt64 ->
6085             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6086               name typ name
6087         | name, FUInt32 ->
6088             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6089               name typ name
6090         | name, FInt32 ->
6091             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6092               name typ name
6093         | name, FChar ->
6094             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6095               name typ name
6096         | name, FOptPercent ->
6097             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6098               typ name name typ name;
6099             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6100       ) cols;
6101       pr "}\n";
6102       pr "\n";
6103       pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6104       pr "{\n";
6105       pr "  print_%s_indent (%s, \"\");\n" typ typ;
6106       pr "}\n";
6107       pr "\n";
6108       pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6109         typ typ typ;
6110       pr "{\n";
6111       pr "  int i;\n";
6112       pr "\n";
6113       pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6114       pr "    printf (\"[%%d] = {\\n\", i);\n";
6115       pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6116       pr "    printf (\"}\\n\");\n";
6117       pr "  }\n";
6118       pr "}\n";
6119       pr "\n";
6120   ) structs;
6121
6122   (* run_<action> actions *)
6123   List.iter (
6124     fun (name, style, _, flags, _, _, _) ->
6125       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6126       pr "{\n";
6127       (match fst style with
6128        | RErr
6129        | RInt _
6130        | RBool _ -> pr "  int r;\n"
6131        | RInt64 _ -> pr "  int64_t r;\n"
6132        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6133        | RString _ -> pr "  char *r;\n"
6134        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6135        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6136        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6137        | RBufferOut _ ->
6138            pr "  char *r;\n";
6139            pr "  size_t size;\n";
6140       );
6141       List.iter (
6142         function
6143         | Pathname n
6144         | Device n | Dev_or_Path n
6145         | String n
6146         | OptString n
6147         | FileIn n
6148         | FileOut n -> pr "  const char *%s;\n" n
6149         | StringList n -> pr "  char **%s;\n" n
6150         | Bool n -> pr "  int %s;\n" n
6151         | Int n -> pr "  int %s;\n" n
6152       ) (snd style);
6153
6154       (* Check and convert parameters. *)
6155       let argc_expected = List.length (snd style) in
6156       pr "  if (argc != %d) {\n" argc_expected;
6157       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6158         argc_expected;
6159       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6160       pr "    return -1;\n";
6161       pr "  }\n";
6162       iteri (
6163         fun i ->
6164           function
6165           | Pathname name
6166           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6167           | OptString name ->
6168               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6169                 name i i
6170           | FileIn name ->
6171               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6172                 name i i
6173           | FileOut name ->
6174               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6175                 name i i
6176           | StringList name ->
6177               pr "  %s = parse_string_list (argv[%d]);\n" name i
6178           | Bool name ->
6179               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6180           | Int name ->
6181               pr "  %s = atoi (argv[%d]);\n" name i
6182       ) (snd style);
6183
6184       (* Call C API function. *)
6185       let fn =
6186         try find_map (function FishAction n -> Some n | _ -> None) flags
6187         with Not_found -> sprintf "guestfs_%s" name in
6188       pr "  r = %s " fn;
6189       generate_c_call_args ~handle:"g" style;
6190       pr ";\n";
6191
6192       (* Check return value for errors and display command results. *)
6193       (match fst style with
6194        | RErr -> pr "  return r;\n"
6195        | RInt _ ->
6196            pr "  if (r == -1) return -1;\n";
6197            pr "  printf (\"%%d\\n\", r);\n";
6198            pr "  return 0;\n"
6199        | RInt64 _ ->
6200            pr "  if (r == -1) return -1;\n";
6201            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6202            pr "  return 0;\n"
6203        | RBool _ ->
6204            pr "  if (r == -1) return -1;\n";
6205            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6206            pr "  return 0;\n"
6207        | RConstString _ ->
6208            pr "  if (r == NULL) return -1;\n";
6209            pr "  printf (\"%%s\\n\", r);\n";
6210            pr "  return 0;\n"
6211        | RConstOptString _ ->
6212            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6213            pr "  return 0;\n"
6214        | RString _ ->
6215            pr "  if (r == NULL) return -1;\n";
6216            pr "  printf (\"%%s\\n\", r);\n";
6217            pr "  free (r);\n";
6218            pr "  return 0;\n"
6219        | RStringList _ ->
6220            pr "  if (r == NULL) return -1;\n";
6221            pr "  print_strings (r);\n";
6222            pr "  free_strings (r);\n";
6223            pr "  return 0;\n"
6224        | RStruct (_, typ) ->
6225            pr "  if (r == NULL) return -1;\n";
6226            pr "  print_%s (r);\n" typ;
6227            pr "  guestfs_free_%s (r);\n" typ;
6228            pr "  return 0;\n"
6229        | RStructList (_, typ) ->
6230            pr "  if (r == NULL) return -1;\n";
6231            pr "  print_%s_list (r);\n" typ;
6232            pr "  guestfs_free_%s_list (r);\n" typ;
6233            pr "  return 0;\n"
6234        | RHashtable _ ->
6235            pr "  if (r == NULL) return -1;\n";
6236            pr "  print_table (r);\n";
6237            pr "  free_strings (r);\n";
6238            pr "  return 0;\n"
6239        | RBufferOut _ ->
6240            pr "  if (r == NULL) return -1;\n";
6241            pr "  fwrite (r, size, 1, stdout);\n";
6242            pr "  free (r);\n";
6243            pr "  return 0;\n"
6244       );
6245       pr "}\n";
6246       pr "\n"
6247   ) all_functions;
6248
6249   (* run_action function *)
6250   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6251   pr "{\n";
6252   List.iter (
6253     fun (name, _, _, flags, _, _, _) ->
6254       let name2 = replace_char name '_' '-' in
6255       let alias =
6256         try find_map (function FishAlias n -> Some n | _ -> None) flags
6257         with Not_found -> name in
6258       pr "  if (";
6259       pr "strcasecmp (cmd, \"%s\") == 0" name;
6260       if name <> name2 then
6261         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6262       if name <> alias then
6263         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6264       pr ")\n";
6265       pr "    return run_%s (cmd, argc, argv);\n" name;
6266       pr "  else\n";
6267   ) all_functions;
6268   pr "    {\n";
6269   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6270   pr "      return -1;\n";
6271   pr "    }\n";
6272   pr "  return 0;\n";
6273   pr "}\n";
6274   pr "\n"
6275
6276 (* Readline completion for guestfish. *)
6277 and generate_fish_completion () =
6278   generate_header CStyle GPLv2;
6279
6280   let all_functions =
6281     List.filter (
6282       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6283     ) all_functions in
6284
6285   pr "\
6286 #include <config.h>
6287
6288 #include <stdio.h>
6289 #include <stdlib.h>
6290 #include <string.h>
6291
6292 #ifdef HAVE_LIBREADLINE
6293 #include <readline/readline.h>
6294 #endif
6295
6296 #include \"fish.h\"
6297
6298 #ifdef HAVE_LIBREADLINE
6299
6300 static const char *const commands[] = {
6301   BUILTIN_COMMANDS_FOR_COMPLETION,
6302 ";
6303
6304   (* Get the commands, including the aliases.  They don't need to be
6305    * sorted - the generator() function just does a dumb linear search.
6306    *)
6307   let commands =
6308     List.map (
6309       fun (name, _, _, flags, _, _, _) ->
6310         let name2 = replace_char name '_' '-' in
6311         let alias =
6312           try find_map (function FishAlias n -> Some n | _ -> None) flags
6313           with Not_found -> name in
6314
6315         if name <> alias then [name2; alias] else [name2]
6316     ) all_functions in
6317   let commands = List.flatten commands in
6318
6319   List.iter (pr "  \"%s\",\n") commands;
6320
6321   pr "  NULL
6322 };
6323
6324 static char *
6325 generator (const char *text, int state)
6326 {
6327   static int index, len;
6328   const char *name;
6329
6330   if (!state) {
6331     index = 0;
6332     len = strlen (text);
6333   }
6334
6335   rl_attempted_completion_over = 1;
6336
6337   while ((name = commands[index]) != NULL) {
6338     index++;
6339     if (strncasecmp (name, text, len) == 0)
6340       return strdup (name);
6341   }
6342
6343   return NULL;
6344 }
6345
6346 #endif /* HAVE_LIBREADLINE */
6347
6348 char **do_completion (const char *text, int start, int end)
6349 {
6350   char **matches = NULL;
6351
6352 #ifdef HAVE_LIBREADLINE
6353   rl_completion_append_character = ' ';
6354
6355   if (start == 0)
6356     matches = rl_completion_matches (text, generator);
6357   else if (complete_dest_paths)
6358     matches = rl_completion_matches (text, complete_dest_paths_generator);
6359 #endif
6360
6361   return matches;
6362 }
6363 ";
6364
6365 (* Generate the POD documentation for guestfish. *)
6366 and generate_fish_actions_pod () =
6367   let all_functions_sorted =
6368     List.filter (
6369       fun (_, _, _, flags, _, _, _) ->
6370         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6371     ) all_functions_sorted in
6372
6373   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6374
6375   List.iter (
6376     fun (name, style, _, flags, _, _, longdesc) ->
6377       let longdesc =
6378         Str.global_substitute rex (
6379           fun s ->
6380             let sub =
6381               try Str.matched_group 1 s
6382               with Not_found ->
6383                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6384             "C<" ^ replace_char sub '_' '-' ^ ">"
6385         ) longdesc in
6386       let name = replace_char name '_' '-' in
6387       let alias =
6388         try find_map (function FishAlias n -> Some n | _ -> None) flags
6389         with Not_found -> name in
6390
6391       pr "=head2 %s" name;
6392       if name <> alias then
6393         pr " | %s" alias;
6394       pr "\n";
6395       pr "\n";
6396       pr " %s" name;
6397       List.iter (
6398         function
6399         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6400         | OptString n -> pr " %s" n
6401         | StringList n -> pr " '%s ...'" n
6402         | Bool _ -> pr " true|false"
6403         | Int n -> pr " %s" n
6404         | FileIn n | FileOut n -> pr " (%s|-)" n
6405       ) (snd style);
6406       pr "\n";
6407       pr "\n";
6408       pr "%s\n\n" longdesc;
6409
6410       if List.exists (function FileIn _ | FileOut _ -> true
6411                       | _ -> false) (snd style) then
6412         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6413
6414       if List.mem ProtocolLimitWarning flags then
6415         pr "%s\n\n" protocol_limit_warning;
6416
6417       if List.mem DangerWillRobinson flags then
6418         pr "%s\n\n" danger_will_robinson;
6419
6420       match deprecation_notice flags with
6421       | None -> ()
6422       | Some txt -> pr "%s\n\n" txt
6423   ) all_functions_sorted
6424
6425 (* Generate a C function prototype. *)
6426 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6427     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6428     ?(prefix = "")
6429     ?handle name style =
6430   if extern then pr "extern ";
6431   if static then pr "static ";
6432   (match fst style with
6433    | RErr -> pr "int "
6434    | RInt _ -> pr "int "
6435    | RInt64 _ -> pr "int64_t "
6436    | RBool _ -> pr "int "
6437    | RConstString _ | RConstOptString _ -> pr "const char *"
6438    | RString _ | RBufferOut _ -> pr "char *"
6439    | RStringList _ | RHashtable _ -> pr "char **"
6440    | RStruct (_, typ) ->
6441        if not in_daemon then pr "struct guestfs_%s *" typ
6442        else pr "guestfs_int_%s *" typ
6443    | RStructList (_, typ) ->
6444        if not in_daemon then pr "struct guestfs_%s_list *" typ
6445        else pr "guestfs_int_%s_list *" typ
6446   );
6447   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6448   pr "%s%s (" prefix name;
6449   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6450     pr "void"
6451   else (
6452     let comma = ref false in
6453     (match handle with
6454      | None -> ()
6455      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6456     );
6457     let next () =
6458       if !comma then (
6459         if single_line then pr ", " else pr ",\n\t\t"
6460       );
6461       comma := true
6462     in
6463     List.iter (
6464       function
6465       | Pathname n
6466       | Device n | Dev_or_Path n
6467       | String n
6468       | OptString n ->
6469           next ();
6470           pr "const char *%s" n
6471       | StringList n ->
6472           next ();
6473           if not in_daemon then pr "char * const* const %s" n
6474           else pr "char **%s" n
6475       | Bool n -> next (); pr "int %s" n
6476       | Int n -> next (); pr "int %s" n
6477       | FileIn n
6478       | FileOut n ->
6479           if not in_daemon then (next (); pr "const char *%s" n)
6480     ) (snd style);
6481     if is_RBufferOut then (next (); pr "size_t *size_r");
6482   );
6483   pr ")";
6484   if semicolon then pr ";";
6485   if newline then pr "\n"
6486
6487 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6488 and generate_c_call_args ?handle ?(decl = false) style =
6489   pr "(";
6490   let comma = ref false in
6491   let next () =
6492     if !comma then pr ", ";
6493     comma := true
6494   in
6495   (match handle with
6496    | None -> ()
6497    | Some handle -> pr "%s" handle; comma := true
6498   );
6499   List.iter (
6500     fun arg ->
6501       next ();
6502       pr "%s" (name_of_argt arg)
6503   ) (snd style);
6504   (* For RBufferOut calls, add implicit &size parameter. *)
6505   if not decl then (
6506     match fst style with
6507     | RBufferOut _ ->
6508         next ();
6509         pr "&size"
6510     | _ -> ()
6511   );
6512   pr ")"
6513
6514 (* Generate the OCaml bindings interface. *)
6515 and generate_ocaml_mli () =
6516   generate_header OCamlStyle LGPLv2;
6517
6518   pr "\
6519 (** For API documentation you should refer to the C API
6520     in the guestfs(3) manual page.  The OCaml API uses almost
6521     exactly the same calls. *)
6522
6523 type t
6524 (** A [guestfs_h] handle. *)
6525
6526 exception Error of string
6527 (** This exception is raised when there is an error. *)
6528
6529 val create : unit -> t
6530
6531 val close : t -> unit
6532 (** Handles are closed by the garbage collector when they become
6533     unreferenced, but callers can also call this in order to
6534     provide predictable cleanup. *)
6535
6536 ";
6537   generate_ocaml_structure_decls ();
6538
6539   (* The actions. *)
6540   List.iter (
6541     fun (name, style, _, _, _, shortdesc, _) ->
6542       generate_ocaml_prototype name style;
6543       pr "(** %s *)\n" shortdesc;
6544       pr "\n"
6545   ) all_functions
6546
6547 (* Generate the OCaml bindings implementation. *)
6548 and generate_ocaml_ml () =
6549   generate_header OCamlStyle LGPLv2;
6550
6551   pr "\
6552 type t
6553 exception Error of string
6554 external create : unit -> t = \"ocaml_guestfs_create\"
6555 external close : t -> unit = \"ocaml_guestfs_close\"
6556
6557 let () =
6558   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6559
6560 ";
6561
6562   generate_ocaml_structure_decls ();
6563
6564   (* The actions. *)
6565   List.iter (
6566     fun (name, style, _, _, _, shortdesc, _) ->
6567       generate_ocaml_prototype ~is_external:true name style;
6568   ) all_functions
6569
6570 (* Generate the OCaml bindings C implementation. *)
6571 and generate_ocaml_c () =
6572   generate_header CStyle LGPLv2;
6573
6574   pr "\
6575 #include <stdio.h>
6576 #include <stdlib.h>
6577 #include <string.h>
6578
6579 #include <caml/config.h>
6580 #include <caml/alloc.h>
6581 #include <caml/callback.h>
6582 #include <caml/fail.h>
6583 #include <caml/memory.h>
6584 #include <caml/mlvalues.h>
6585 #include <caml/signals.h>
6586
6587 #include <guestfs.h>
6588
6589 #include \"guestfs_c.h\"
6590
6591 /* Copy a hashtable of string pairs into an assoc-list.  We return
6592  * the list in reverse order, but hashtables aren't supposed to be
6593  * ordered anyway.
6594  */
6595 static CAMLprim value
6596 copy_table (char * const * argv)
6597 {
6598   CAMLparam0 ();
6599   CAMLlocal5 (rv, pairv, kv, vv, cons);
6600   int i;
6601
6602   rv = Val_int (0);
6603   for (i = 0; argv[i] != NULL; i += 2) {
6604     kv = caml_copy_string (argv[i]);
6605     vv = caml_copy_string (argv[i+1]);
6606     pairv = caml_alloc (2, 0);
6607     Store_field (pairv, 0, kv);
6608     Store_field (pairv, 1, vv);
6609     cons = caml_alloc (2, 0);
6610     Store_field (cons, 1, rv);
6611     rv = cons;
6612     Store_field (cons, 0, pairv);
6613   }
6614
6615   CAMLreturn (rv);
6616 }
6617
6618 ";
6619
6620   (* Struct copy functions. *)
6621   List.iter (
6622     fun (typ, cols) ->
6623       let has_optpercent_col =
6624         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6625
6626       pr "static CAMLprim value\n";
6627       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6628       pr "{\n";
6629       pr "  CAMLparam0 ();\n";
6630       if has_optpercent_col then
6631         pr "  CAMLlocal3 (rv, v, v2);\n"
6632       else
6633         pr "  CAMLlocal2 (rv, v);\n";
6634       pr "\n";
6635       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6636       iteri (
6637         fun i col ->
6638           (match col with
6639            | name, FString ->
6640                pr "  v = caml_copy_string (%s->%s);\n" typ name
6641            | name, FBuffer ->
6642                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6643                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6644                  typ name typ name
6645            | name, FUUID ->
6646                pr "  v = caml_alloc_string (32);\n";
6647                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6648            | name, (FBytes|FInt64|FUInt64) ->
6649                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6650            | name, (FInt32|FUInt32) ->
6651                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6652            | name, FOptPercent ->
6653                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6654                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6655                pr "    v = caml_alloc (1, 0);\n";
6656                pr "    Store_field (v, 0, v2);\n";
6657                pr "  } else /* None */\n";
6658                pr "    v = Val_int (0);\n";
6659            | name, FChar ->
6660                pr "  v = Val_int (%s->%s);\n" typ name
6661           );
6662           pr "  Store_field (rv, %d, v);\n" i
6663       ) cols;
6664       pr "  CAMLreturn (rv);\n";
6665       pr "}\n";
6666       pr "\n";
6667
6668       pr "static CAMLprim value\n";
6669       pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
6670         typ typ typ;
6671       pr "{\n";
6672       pr "  CAMLparam0 ();\n";
6673       pr "  CAMLlocal2 (rv, v);\n";
6674       pr "  int i;\n";
6675       pr "\n";
6676       pr "  if (%ss->len == 0)\n" typ;
6677       pr "    CAMLreturn (Atom (0));\n";
6678       pr "  else {\n";
6679       pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6680       pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6681       pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6682       pr "      caml_modify (&Field (rv, i), v);\n";
6683       pr "    }\n";
6684       pr "    CAMLreturn (rv);\n";
6685       pr "  }\n";
6686       pr "}\n";
6687       pr "\n";
6688   ) structs;
6689
6690   (* The wrappers. *)
6691   List.iter (
6692     fun (name, style, _, _, _, _, _) ->
6693       let params =
6694         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6695
6696       let needs_extra_vs =
6697         match fst style with RConstOptString _ -> true | _ -> false in
6698
6699       pr "CAMLprim value\n";
6700       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6701       List.iter (pr ", value %s") (List.tl params);
6702       pr ")\n";
6703       pr "{\n";
6704
6705       (match params with
6706        | [p1; p2; p3; p4; p5] ->
6707            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6708        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6709            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6710            pr "  CAMLxparam%d (%s);\n"
6711              (List.length rest) (String.concat ", " rest)
6712        | ps ->
6713            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6714       );
6715       if not needs_extra_vs then
6716         pr "  CAMLlocal1 (rv);\n"
6717       else
6718         pr "  CAMLlocal3 (rv, v, v2);\n";
6719       pr "\n";
6720
6721       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6722       pr "  if (g == NULL)\n";
6723       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6724       pr "\n";
6725
6726       List.iter (
6727         function
6728         | Pathname n
6729         | Device n | Dev_or_Path n
6730         | String n
6731         | FileIn n
6732         | FileOut n ->
6733             pr "  const char *%s = String_val (%sv);\n" n n
6734         | OptString n ->
6735             pr "  const char *%s =\n" n;
6736             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6737               n n
6738         | StringList n ->
6739             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6740         | Bool n ->
6741             pr "  int %s = Bool_val (%sv);\n" n n
6742         | Int n ->
6743             pr "  int %s = Int_val (%sv);\n" n n
6744       ) (snd style);
6745       let error_code =
6746         match fst style with
6747         | RErr -> pr "  int r;\n"; "-1"
6748         | RInt _ -> pr "  int r;\n"; "-1"
6749         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6750         | RBool _ -> pr "  int r;\n"; "-1"
6751         | RConstString _ | RConstOptString _ ->
6752             pr "  const char *r;\n"; "NULL"
6753         | RString _ -> pr "  char *r;\n"; "NULL"
6754         | RStringList _ ->
6755             pr "  int i;\n";
6756             pr "  char **r;\n";
6757             "NULL"
6758         | RStruct (_, typ) ->
6759             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6760         | RStructList (_, typ) ->
6761             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6762         | RHashtable _ ->
6763             pr "  int i;\n";
6764             pr "  char **r;\n";
6765             "NULL"
6766         | RBufferOut _ ->
6767             pr "  char *r;\n";
6768             pr "  size_t size;\n";
6769             "NULL" in
6770       pr "\n";
6771
6772       pr "  caml_enter_blocking_section ();\n";
6773       pr "  r = guestfs_%s " name;
6774       generate_c_call_args ~handle:"g" style;
6775       pr ";\n";
6776       pr "  caml_leave_blocking_section ();\n";
6777
6778       List.iter (
6779         function
6780         | StringList n ->
6781             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6782         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6783         | FileIn _ | FileOut _ -> ()
6784       ) (snd style);
6785
6786       pr "  if (r == %s)\n" error_code;
6787       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6788       pr "\n";
6789
6790       (match fst style with
6791        | RErr -> pr "  rv = Val_unit;\n"
6792        | RInt _ -> pr "  rv = Val_int (r);\n"
6793        | RInt64 _ ->
6794            pr "  rv = caml_copy_int64 (r);\n"
6795        | RBool _ -> pr "  rv = Val_bool (r);\n"
6796        | RConstString _ ->
6797            pr "  rv = caml_copy_string (r);\n"
6798        | RConstOptString _ ->
6799            pr "  if (r) { /* Some string */\n";
6800            pr "    v = caml_alloc (1, 0);\n";
6801            pr "    v2 = caml_copy_string (r);\n";
6802            pr "    Store_field (v, 0, v2);\n";
6803            pr "  } else /* None */\n";
6804            pr "    v = Val_int (0);\n";
6805        | RString _ ->
6806            pr "  rv = caml_copy_string (r);\n";
6807            pr "  free (r);\n"
6808        | RStringList _ ->
6809            pr "  rv = caml_copy_string_array ((const char **) r);\n";
6810            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6811            pr "  free (r);\n"
6812        | RStruct (_, typ) ->
6813            pr "  rv = copy_%s (r);\n" typ;
6814            pr "  guestfs_free_%s (r);\n" typ;
6815        | RStructList (_, typ) ->
6816            pr "  rv = copy_%s_list (r);\n" typ;
6817            pr "  guestfs_free_%s_list (r);\n" typ;
6818        | RHashtable _ ->
6819            pr "  rv = copy_table (r);\n";
6820            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6821            pr "  free (r);\n";
6822        | RBufferOut _ ->
6823            pr "  rv = caml_alloc_string (size);\n";
6824            pr "  memcpy (String_val (rv), r, size);\n";
6825       );
6826
6827       pr "  CAMLreturn (rv);\n";
6828       pr "}\n";
6829       pr "\n";
6830
6831       if List.length params > 5 then (
6832         pr "CAMLprim value\n";
6833         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6834         pr "{\n";
6835         pr "  return ocaml_guestfs_%s (argv[0]" name;
6836         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6837         pr ");\n";
6838         pr "}\n";
6839         pr "\n"
6840       )
6841   ) all_functions
6842
6843 and generate_ocaml_structure_decls () =
6844   List.iter (
6845     fun (typ, cols) ->
6846       pr "type %s = {\n" typ;
6847       List.iter (
6848         function
6849         | name, FString -> pr "  %s : string;\n" name
6850         | name, FBuffer -> pr "  %s : string;\n" name
6851         | name, FUUID -> pr "  %s : string;\n" name
6852         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
6853         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
6854         | name, FChar -> pr "  %s : char;\n" name
6855         | name, FOptPercent -> pr "  %s : float option;\n" name
6856       ) cols;
6857       pr "}\n";
6858       pr "\n"
6859   ) structs
6860
6861 and generate_ocaml_prototype ?(is_external = false) name style =
6862   if is_external then pr "external " else pr "val ";
6863   pr "%s : t -> " name;
6864   List.iter (
6865     function
6866     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6867     | OptString _ -> pr "string option -> "
6868     | StringList _ -> pr "string array -> "
6869     | Bool _ -> pr "bool -> "
6870     | Int _ -> pr "int -> "
6871   ) (snd style);
6872   (match fst style with
6873    | RErr -> pr "unit" (* all errors are turned into exceptions *)
6874    | RInt _ -> pr "int"
6875    | RInt64 _ -> pr "int64"
6876    | RBool _ -> pr "bool"
6877    | RConstString _ -> pr "string"
6878    | RConstOptString _ -> pr "string option"
6879    | RString _ | RBufferOut _ -> pr "string"
6880    | RStringList _ -> pr "string array"
6881    | RStruct (_, typ) -> pr "%s" typ
6882    | RStructList (_, typ) -> pr "%s array" typ
6883    | RHashtable _ -> pr "(string * string) list"
6884   );
6885   if is_external then (
6886     pr " = ";
6887     if List.length (snd style) + 1 > 5 then
6888       pr "\"ocaml_guestfs_%s_byte\" " name;
6889     pr "\"ocaml_guestfs_%s\"" name
6890   );
6891   pr "\n"
6892
6893 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
6894 and generate_perl_xs () =
6895   generate_header CStyle LGPLv2;
6896
6897   pr "\
6898 #include \"EXTERN.h\"
6899 #include \"perl.h\"
6900 #include \"XSUB.h\"
6901
6902 #include <guestfs.h>
6903
6904 #ifndef PRId64
6905 #define PRId64 \"lld\"
6906 #endif
6907
6908 static SV *
6909 my_newSVll(long long val) {
6910 #ifdef USE_64_BIT_ALL
6911   return newSViv(val);
6912 #else
6913   char buf[100];
6914   int len;
6915   len = snprintf(buf, 100, \"%%\" PRId64, val);
6916   return newSVpv(buf, len);
6917 #endif
6918 }
6919
6920 #ifndef PRIu64
6921 #define PRIu64 \"llu\"
6922 #endif
6923
6924 static SV *
6925 my_newSVull(unsigned long long val) {
6926 #ifdef USE_64_BIT_ALL
6927   return newSVuv(val);
6928 #else
6929   char buf[100];
6930   int len;
6931   len = snprintf(buf, 100, \"%%\" PRIu64, val);
6932   return newSVpv(buf, len);
6933 #endif
6934 }
6935
6936 /* http://www.perlmonks.org/?node_id=680842 */
6937 static char **
6938 XS_unpack_charPtrPtr (SV *arg) {
6939   char **ret;
6940   AV *av;
6941   I32 i;
6942
6943   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
6944     croak (\"array reference expected\");
6945
6946   av = (AV *)SvRV (arg);
6947   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
6948   if (!ret)
6949     croak (\"malloc failed\");
6950
6951   for (i = 0; i <= av_len (av); i++) {
6952     SV **elem = av_fetch (av, i, 0);
6953
6954     if (!elem || !*elem)
6955       croak (\"missing element in list\");
6956
6957     ret[i] = SvPV_nolen (*elem);
6958   }
6959
6960   ret[i] = NULL;
6961
6962   return ret;
6963 }
6964
6965 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
6966
6967 PROTOTYPES: ENABLE
6968
6969 guestfs_h *
6970 _create ()
6971    CODE:
6972       RETVAL = guestfs_create ();
6973       if (!RETVAL)
6974         croak (\"could not create guestfs handle\");
6975       guestfs_set_error_handler (RETVAL, NULL, NULL);
6976  OUTPUT:
6977       RETVAL
6978
6979 void
6980 DESTROY (g)
6981       guestfs_h *g;
6982  PPCODE:
6983       guestfs_close (g);
6984
6985 ";
6986
6987   List.iter (
6988     fun (name, style, _, _, _, _, _) ->
6989       (match fst style with
6990        | RErr -> pr "void\n"
6991        | RInt _ -> pr "SV *\n"
6992        | RInt64 _ -> pr "SV *\n"
6993        | RBool _ -> pr "SV *\n"
6994        | RConstString _ -> pr "SV *\n"
6995        | RConstOptString _ -> pr "SV *\n"
6996        | RString _ -> pr "SV *\n"
6997        | RBufferOut _ -> pr "SV *\n"
6998        | RStringList _
6999        | RStruct _ | RStructList _
7000        | RHashtable _ ->
7001            pr "void\n" (* all lists returned implictly on the stack *)
7002       );
7003       (* Call and arguments. *)
7004       pr "%s " name;
7005       generate_c_call_args ~handle:"g" ~decl:true style;
7006       pr "\n";
7007       pr "      guestfs_h *g;\n";
7008       iteri (
7009         fun i ->
7010           function
7011           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7012               pr "      char *%s;\n" n
7013           | OptString n ->
7014               (* http://www.perlmonks.org/?node_id=554277
7015                * Note that the implicit handle argument means we have
7016                * to add 1 to the ST(x) operator.
7017                *)
7018               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7019           | StringList n -> pr "      char **%s;\n" n
7020           | Bool n -> pr "      int %s;\n" n
7021           | Int n -> pr "      int %s;\n" n
7022       ) (snd style);
7023
7024       let do_cleanups () =
7025         List.iter (
7026           function
7027           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7028           | FileIn _ | FileOut _ -> ()
7029           | StringList n -> pr "      free (%s);\n" n
7030         ) (snd style)
7031       in
7032
7033       (* Code. *)
7034       (match fst style with
7035        | RErr ->
7036            pr "PREINIT:\n";
7037            pr "      int r;\n";
7038            pr " PPCODE:\n";
7039            pr "      r = guestfs_%s " name;
7040            generate_c_call_args ~handle:"g" style;
7041            pr ";\n";
7042            do_cleanups ();
7043            pr "      if (r == -1)\n";
7044            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7045        | RInt n
7046        | RBool n ->
7047            pr "PREINIT:\n";
7048            pr "      int %s;\n" n;
7049            pr "   CODE:\n";
7050            pr "      %s = guestfs_%s " n name;
7051            generate_c_call_args ~handle:"g" style;
7052            pr ";\n";
7053            do_cleanups ();
7054            pr "      if (%s == -1)\n" n;
7055            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7056            pr "      RETVAL = newSViv (%s);\n" n;
7057            pr " OUTPUT:\n";
7058            pr "      RETVAL\n"
7059        | RInt64 n ->
7060            pr "PREINIT:\n";
7061            pr "      int64_t %s;\n" n;
7062            pr "   CODE:\n";
7063            pr "      %s = guestfs_%s " n name;
7064            generate_c_call_args ~handle:"g" style;
7065            pr ";\n";
7066            do_cleanups ();
7067            pr "      if (%s == -1)\n" n;
7068            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7069            pr "      RETVAL = my_newSVll (%s);\n" n;
7070            pr " OUTPUT:\n";
7071            pr "      RETVAL\n"
7072        | RConstString n ->
7073            pr "PREINIT:\n";
7074            pr "      const char *%s;\n" n;
7075            pr "   CODE:\n";
7076            pr "      %s = guestfs_%s " n name;
7077            generate_c_call_args ~handle:"g" style;
7078            pr ";\n";
7079            do_cleanups ();
7080            pr "      if (%s == NULL)\n" n;
7081            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7082            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7083            pr " OUTPUT:\n";
7084            pr "      RETVAL\n"
7085        | RConstOptString n ->
7086            pr "PREINIT:\n";
7087            pr "      const char *%s;\n" n;
7088            pr "   CODE:\n";
7089            pr "      %s = guestfs_%s " n name;
7090            generate_c_call_args ~handle:"g" style;
7091            pr ";\n";
7092            do_cleanups ();
7093            pr "      if (%s == NULL)\n" n;
7094            pr "        RETVAL = &PL_sv_undef;\n";
7095            pr "      else\n";
7096            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7097            pr " OUTPUT:\n";
7098            pr "      RETVAL\n"
7099        | RString n ->
7100            pr "PREINIT:\n";
7101            pr "      char *%s;\n" n;
7102            pr "   CODE:\n";
7103            pr "      %s = guestfs_%s " n name;
7104            generate_c_call_args ~handle:"g" style;
7105            pr ";\n";
7106            do_cleanups ();
7107            pr "      if (%s == NULL)\n" n;
7108            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7109            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7110            pr "      free (%s);\n" n;
7111            pr " OUTPUT:\n";
7112            pr "      RETVAL\n"
7113        | RStringList n | RHashtable n ->
7114            pr "PREINIT:\n";
7115            pr "      char **%s;\n" n;
7116            pr "      int i, n;\n";
7117            pr " PPCODE:\n";
7118            pr "      %s = guestfs_%s " n name;
7119            generate_c_call_args ~handle:"g" style;
7120            pr ";\n";
7121            do_cleanups ();
7122            pr "      if (%s == NULL)\n" n;
7123            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7124            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7125            pr "      EXTEND (SP, n);\n";
7126            pr "      for (i = 0; i < n; ++i) {\n";
7127            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7128            pr "        free (%s[i]);\n" n;
7129            pr "      }\n";
7130            pr "      free (%s);\n" n;
7131        | RStruct (n, typ) ->
7132            let cols = cols_of_struct typ in
7133            generate_perl_struct_code typ cols name style n do_cleanups
7134        | RStructList (n, typ) ->
7135            let cols = cols_of_struct typ in
7136            generate_perl_struct_list_code typ cols name style n do_cleanups
7137        | RBufferOut n ->
7138            pr "PREINIT:\n";
7139            pr "      char *%s;\n" n;
7140            pr "      size_t size;\n";
7141            pr "   CODE:\n";
7142            pr "      %s = guestfs_%s " n name;
7143            generate_c_call_args ~handle:"g" style;
7144            pr ";\n";
7145            do_cleanups ();
7146            pr "      if (%s == NULL)\n" n;
7147            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7148            pr "      RETVAL = newSVpv (%s, size);\n" n;
7149            pr "      free (%s);\n" n;
7150            pr " OUTPUT:\n";
7151            pr "      RETVAL\n"
7152       );
7153
7154       pr "\n"
7155   ) all_functions
7156
7157 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7158   pr "PREINIT:\n";
7159   pr "      struct guestfs_%s_list *%s;\n" typ n;
7160   pr "      int i;\n";
7161   pr "      HV *hv;\n";
7162   pr " PPCODE:\n";
7163   pr "      %s = guestfs_%s " n name;
7164   generate_c_call_args ~handle:"g" style;
7165   pr ";\n";
7166   do_cleanups ();
7167   pr "      if (%s == NULL)\n" n;
7168   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7169   pr "      EXTEND (SP, %s->len);\n" n;
7170   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7171   pr "        hv = newHV ();\n";
7172   List.iter (
7173     function
7174     | name, FString ->
7175         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7176           name (String.length name) n name
7177     | name, FUUID ->
7178         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7179           name (String.length name) n name
7180     | name, FBuffer ->
7181         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7182           name (String.length name) n name n name
7183     | name, (FBytes|FUInt64) ->
7184         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7185           name (String.length name) n name
7186     | name, FInt64 ->
7187         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7188           name (String.length name) n name
7189     | name, (FInt32|FUInt32) ->
7190         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7191           name (String.length name) n name
7192     | name, FChar ->
7193         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7194           name (String.length name) n name
7195     | name, FOptPercent ->
7196         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7197           name (String.length name) n name
7198   ) cols;
7199   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7200   pr "      }\n";
7201   pr "      guestfs_free_%s_list (%s);\n" typ n
7202
7203 and generate_perl_struct_code typ cols name style n do_cleanups =
7204   pr "PREINIT:\n";
7205   pr "      struct guestfs_%s *%s;\n" typ n;
7206   pr " PPCODE:\n";
7207   pr "      %s = guestfs_%s " n name;
7208   generate_c_call_args ~handle:"g" style;
7209   pr ";\n";
7210   do_cleanups ();
7211   pr "      if (%s == NULL)\n" n;
7212   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7213   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7214   List.iter (
7215     fun ((name, _) as col) ->
7216       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7217
7218       match col with
7219       | name, FString ->
7220           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7221             n name
7222       | name, FBuffer ->
7223           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7224             n name n name
7225       | name, FUUID ->
7226           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7227             n name
7228       | name, (FBytes|FUInt64) ->
7229           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7230             n name
7231       | name, FInt64 ->
7232           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7233             n name
7234       | name, (FInt32|FUInt32) ->
7235           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7236             n name
7237       | name, FChar ->
7238           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7239             n name
7240       | name, FOptPercent ->
7241           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7242             n name
7243   ) cols;
7244   pr "      free (%s);\n" n
7245
7246 (* Generate Sys/Guestfs.pm. *)
7247 and generate_perl_pm () =
7248   generate_header HashStyle LGPLv2;
7249
7250   pr "\
7251 =pod
7252
7253 =head1 NAME
7254
7255 Sys::Guestfs - Perl bindings for libguestfs
7256
7257 =head1 SYNOPSIS
7258
7259  use Sys::Guestfs;
7260
7261  my $h = Sys::Guestfs->new ();
7262  $h->add_drive ('guest.img');
7263  $h->launch ();
7264  $h->wait_ready ();
7265  $h->mount ('/dev/sda1', '/');
7266  $h->touch ('/hello');
7267  $h->sync ();
7268
7269 =head1 DESCRIPTION
7270
7271 The C<Sys::Guestfs> module provides a Perl XS binding to the
7272 libguestfs API for examining and modifying virtual machine
7273 disk images.
7274
7275 Amongst the things this is good for: making batch configuration
7276 changes to guests, getting disk used/free statistics (see also:
7277 virt-df), migrating between virtualization systems (see also:
7278 virt-p2v), performing partial backups, performing partial guest
7279 clones, cloning guests and changing registry/UUID/hostname info, and
7280 much else besides.
7281
7282 Libguestfs uses Linux kernel and qemu code, and can access any type of
7283 guest filesystem that Linux and qemu can, including but not limited
7284 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7285 schemes, qcow, qcow2, vmdk.
7286
7287 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7288 LVs, what filesystem is in each LV, etc.).  It can also run commands
7289 in the context of the guest.  Also you can access filesystems over FTP.
7290
7291 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7292 functions for using libguestfs from Perl, including integration
7293 with libvirt.
7294
7295 =head1 ERRORS
7296
7297 All errors turn into calls to C<croak> (see L<Carp(3)>).
7298
7299 =head1 METHODS
7300
7301 =over 4
7302
7303 =cut
7304
7305 package Sys::Guestfs;
7306
7307 use strict;
7308 use warnings;
7309
7310 require XSLoader;
7311 XSLoader::load ('Sys::Guestfs');
7312
7313 =item $h = Sys::Guestfs->new ();
7314
7315 Create a new guestfs handle.
7316
7317 =cut
7318
7319 sub new {
7320   my $proto = shift;
7321   my $class = ref ($proto) || $proto;
7322
7323   my $self = Sys::Guestfs::_create ();
7324   bless $self, $class;
7325   return $self;
7326 }
7327
7328 ";
7329
7330   (* Actions.  We only need to print documentation for these as
7331    * they are pulled in from the XS code automatically.
7332    *)
7333   List.iter (
7334     fun (name, style, _, flags, _, _, longdesc) ->
7335       if not (List.mem NotInDocs flags) then (
7336         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7337         pr "=item ";
7338         generate_perl_prototype name style;
7339         pr "\n\n";
7340         pr "%s\n\n" longdesc;
7341         if List.mem ProtocolLimitWarning flags then
7342           pr "%s\n\n" protocol_limit_warning;
7343         if List.mem DangerWillRobinson flags then
7344           pr "%s\n\n" danger_will_robinson;
7345         match deprecation_notice flags with
7346         | None -> ()
7347         | Some txt -> pr "%s\n\n" txt
7348       )
7349   ) all_functions_sorted;
7350
7351   (* End of file. *)
7352   pr "\
7353 =cut
7354
7355 1;
7356
7357 =back
7358
7359 =head1 COPYRIGHT
7360
7361 Copyright (C) 2009 Red Hat Inc.
7362
7363 =head1 LICENSE
7364
7365 Please see the file COPYING.LIB for the full license.
7366
7367 =head1 SEE ALSO
7368
7369 L<guestfs(3)>,
7370 L<guestfish(1)>,
7371 L<http://libguestfs.org>,
7372 L<Sys::Guestfs::Lib(3)>.
7373
7374 =cut
7375 "
7376
7377 and generate_perl_prototype name style =
7378   (match fst style with
7379    | RErr -> ()
7380    | RBool n
7381    | RInt n
7382    | RInt64 n
7383    | RConstString n
7384    | RConstOptString n
7385    | RString n
7386    | RBufferOut n -> pr "$%s = " n
7387    | RStruct (n,_)
7388    | RHashtable n -> pr "%%%s = " n
7389    | RStringList n
7390    | RStructList (n,_) -> pr "@%s = " n
7391   );
7392   pr "$h->%s (" name;
7393   let comma = ref false in
7394   List.iter (
7395     fun arg ->
7396       if !comma then pr ", ";
7397       comma := true;
7398       match arg with
7399       | Pathname n | Device n | Dev_or_Path n | String n
7400       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7401           pr "$%s" n
7402       | StringList n ->
7403           pr "\\@%s" n
7404   ) (snd style);
7405   pr ");"
7406
7407 (* Generate Python C module. *)
7408 and generate_python_c () =
7409   generate_header CStyle LGPLv2;
7410
7411   pr "\
7412 #include <stdio.h>
7413 #include <stdlib.h>
7414 #include <assert.h>
7415
7416 #include <Python.h>
7417
7418 #include \"guestfs.h\"
7419
7420 typedef struct {
7421   PyObject_HEAD
7422   guestfs_h *g;
7423 } Pyguestfs_Object;
7424
7425 static guestfs_h *
7426 get_handle (PyObject *obj)
7427 {
7428   assert (obj);
7429   assert (obj != Py_None);
7430   return ((Pyguestfs_Object *) obj)->g;
7431 }
7432
7433 static PyObject *
7434 put_handle (guestfs_h *g)
7435 {
7436   assert (g);
7437   return
7438     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7439 }
7440
7441 /* This list should be freed (but not the strings) after use. */
7442 static const char **
7443 get_string_list (PyObject *obj)
7444 {
7445   int i, len;
7446   const char **r;
7447
7448   assert (obj);
7449
7450   if (!PyList_Check (obj)) {
7451     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7452     return NULL;
7453   }
7454
7455   len = PyList_Size (obj);
7456   r = malloc (sizeof (char *) * (len+1));
7457   if (r == NULL) {
7458     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7459     return NULL;
7460   }
7461
7462   for (i = 0; i < len; ++i)
7463     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7464   r[len] = NULL;
7465
7466   return r;
7467 }
7468
7469 static PyObject *
7470 put_string_list (char * const * const argv)
7471 {
7472   PyObject *list;
7473   int argc, i;
7474
7475   for (argc = 0; argv[argc] != NULL; ++argc)
7476     ;
7477
7478   list = PyList_New (argc);
7479   for (i = 0; i < argc; ++i)
7480     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7481
7482   return list;
7483 }
7484
7485 static PyObject *
7486 put_table (char * const * const argv)
7487 {
7488   PyObject *list, *item;
7489   int argc, i;
7490
7491   for (argc = 0; argv[argc] != NULL; ++argc)
7492     ;
7493
7494   list = PyList_New (argc >> 1);
7495   for (i = 0; i < argc; i += 2) {
7496     item = PyTuple_New (2);
7497     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7498     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7499     PyList_SetItem (list, i >> 1, item);
7500   }
7501
7502   return list;
7503 }
7504
7505 static void
7506 free_strings (char **argv)
7507 {
7508   int argc;
7509
7510   for (argc = 0; argv[argc] != NULL; ++argc)
7511     free (argv[argc]);
7512   free (argv);
7513 }
7514
7515 static PyObject *
7516 py_guestfs_create (PyObject *self, PyObject *args)
7517 {
7518   guestfs_h *g;
7519
7520   g = guestfs_create ();
7521   if (g == NULL) {
7522     PyErr_SetString (PyExc_RuntimeError,
7523                      \"guestfs.create: failed to allocate handle\");
7524     return NULL;
7525   }
7526   guestfs_set_error_handler (g, NULL, NULL);
7527   return put_handle (g);
7528 }
7529
7530 static PyObject *
7531 py_guestfs_close (PyObject *self, PyObject *args)
7532 {
7533   PyObject *py_g;
7534   guestfs_h *g;
7535
7536   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7537     return NULL;
7538   g = get_handle (py_g);
7539
7540   guestfs_close (g);
7541
7542   Py_INCREF (Py_None);
7543   return Py_None;
7544 }
7545
7546 ";
7547
7548   let emit_put_list_function typ =
7549     pr "static PyObject *\n";
7550     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7551     pr "{\n";
7552     pr "  PyObject *list;\n";
7553     pr "  int i;\n";
7554     pr "\n";
7555     pr "  list = PyList_New (%ss->len);\n" typ;
7556     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7557     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7558     pr "  return list;\n";
7559     pr "};\n";
7560     pr "\n"
7561   in
7562
7563   (* Structures, turned into Python dictionaries. *)
7564   List.iter (
7565     fun (typ, cols) ->
7566       pr "static PyObject *\n";
7567       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7568       pr "{\n";
7569       pr "  PyObject *dict;\n";
7570       pr "\n";
7571       pr "  dict = PyDict_New ();\n";
7572       List.iter (
7573         function
7574         | name, FString ->
7575             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7576             pr "                        PyString_FromString (%s->%s));\n"
7577               typ name
7578         | name, FBuffer ->
7579             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7580             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7581               typ name typ name
7582         | name, FUUID ->
7583             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7584             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7585               typ name
7586         | name, (FBytes|FUInt64) ->
7587             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7588             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7589               typ name
7590         | name, FInt64 ->
7591             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7592             pr "                        PyLong_FromLongLong (%s->%s));\n"
7593               typ name
7594         | name, FUInt32 ->
7595             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7596             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7597               typ name
7598         | name, FInt32 ->
7599             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7600             pr "                        PyLong_FromLong (%s->%s));\n"
7601               typ name
7602         | name, FOptPercent ->
7603             pr "  if (%s->%s >= 0)\n" typ name;
7604             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7605             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7606               typ name;
7607             pr "  else {\n";
7608             pr "    Py_INCREF (Py_None);\n";
7609             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);" name;
7610             pr "  }\n"
7611         | name, FChar ->
7612             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7613             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7614       ) cols;
7615       pr "  return dict;\n";
7616       pr "};\n";
7617       pr "\n";
7618
7619   ) structs;
7620
7621   (* Emit a put_TYPE_list function definition only if that function is used. *)
7622   List.iter (
7623     function
7624     | typ, (RStructListOnly | RStructAndList) ->
7625         (* generate the function for typ *)
7626         emit_put_list_function typ
7627     | typ, _ -> () (* empty *)
7628   ) rstructs_used;
7629
7630   (* Python wrapper functions. *)
7631   List.iter (
7632     fun (name, style, _, _, _, _, _) ->
7633       pr "static PyObject *\n";
7634       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7635       pr "{\n";
7636
7637       pr "  PyObject *py_g;\n";
7638       pr "  guestfs_h *g;\n";
7639       pr "  PyObject *py_r;\n";
7640
7641       let error_code =
7642         match fst style with
7643         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7644         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7645         | RConstString _ | RConstOptString _ ->
7646             pr "  const char *r;\n"; "NULL"
7647         | RString _ -> pr "  char *r;\n"; "NULL"
7648         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7649         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7650         | RStructList (_, typ) ->
7651             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7652         | RBufferOut _ ->
7653             pr "  char *r;\n";
7654             pr "  size_t size;\n";
7655             "NULL" in
7656
7657       List.iter (
7658         function
7659         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7660             pr "  const char *%s;\n" n
7661         | OptString n -> pr "  const char *%s;\n" n
7662         | StringList n ->
7663             pr "  PyObject *py_%s;\n" n;
7664             pr "  const char **%s;\n" n
7665         | Bool n -> pr "  int %s;\n" n
7666         | Int n -> pr "  int %s;\n" n
7667       ) (snd style);
7668
7669       pr "\n";
7670
7671       (* Convert the parameters. *)
7672       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7673       List.iter (
7674         function
7675         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7676         | OptString _ -> pr "z"
7677         | StringList _ -> pr "O"
7678         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7679         | Int _ -> pr "i"
7680       ) (snd style);
7681       pr ":guestfs_%s\",\n" name;
7682       pr "                         &py_g";
7683       List.iter (
7684         function
7685         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7686         | OptString n -> pr ", &%s" n
7687         | StringList n -> pr ", &py_%s" n
7688         | Bool n -> pr ", &%s" n
7689         | Int n -> pr ", &%s" n
7690       ) (snd style);
7691
7692       pr "))\n";
7693       pr "    return NULL;\n";
7694
7695       pr "  g = get_handle (py_g);\n";
7696       List.iter (
7697         function
7698         | Pathname _ | Device _ | Dev_or_Path _ | String _
7699         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7700         | StringList n ->
7701             pr "  %s = get_string_list (py_%s);\n" n n;
7702             pr "  if (!%s) return NULL;\n" n
7703       ) (snd style);
7704
7705       pr "\n";
7706
7707       pr "  r = guestfs_%s " name;
7708       generate_c_call_args ~handle:"g" style;
7709       pr ";\n";
7710
7711       List.iter (
7712         function
7713         | Pathname _ | Device _ | Dev_or_Path _ | String _
7714         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7715         | StringList n ->
7716             pr "  free (%s);\n" n
7717       ) (snd style);
7718
7719       pr "  if (r == %s) {\n" error_code;
7720       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7721       pr "    return NULL;\n";
7722       pr "  }\n";
7723       pr "\n";
7724
7725       (match fst style with
7726        | RErr ->
7727            pr "  Py_INCREF (Py_None);\n";
7728            pr "  py_r = Py_None;\n"
7729        | RInt _
7730        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7731        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7732        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7733        | RConstOptString _ ->
7734            pr "  if (r)\n";
7735            pr "    py_r = PyString_FromString (r);\n";
7736            pr "  else {\n";
7737            pr "    Py_INCREF (Py_None);\n";
7738            pr "    py_r = Py_None;\n";
7739            pr "  }\n"
7740        | RString _ ->
7741            pr "  py_r = PyString_FromString (r);\n";
7742            pr "  free (r);\n"
7743        | RStringList _ ->
7744            pr "  py_r = put_string_list (r);\n";
7745            pr "  free_strings (r);\n"
7746        | RStruct (_, typ) ->
7747            pr "  py_r = put_%s (r);\n" typ;
7748            pr "  guestfs_free_%s (r);\n" typ
7749        | RStructList (_, typ) ->
7750            pr "  py_r = put_%s_list (r);\n" typ;
7751            pr "  guestfs_free_%s_list (r);\n" typ
7752        | RHashtable n ->
7753            pr "  py_r = put_table (r);\n";
7754            pr "  free_strings (r);\n"
7755        | RBufferOut _ ->
7756            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7757            pr "  free (r);\n"
7758       );
7759
7760       pr "  return py_r;\n";
7761       pr "}\n";
7762       pr "\n"
7763   ) all_functions;
7764
7765   (* Table of functions. *)
7766   pr "static PyMethodDef methods[] = {\n";
7767   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7768   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7769   List.iter (
7770     fun (name, _, _, _, _, _, _) ->
7771       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7772         name name
7773   ) all_functions;
7774   pr "  { NULL, NULL, 0, NULL }\n";
7775   pr "};\n";
7776   pr "\n";
7777
7778   (* Init function. *)
7779   pr "\
7780 void
7781 initlibguestfsmod (void)
7782 {
7783   static int initialized = 0;
7784
7785   if (initialized) return;
7786   Py_InitModule ((char *) \"libguestfsmod\", methods);
7787   initialized = 1;
7788 }
7789 "
7790
7791 (* Generate Python module. *)
7792 and generate_python_py () =
7793   generate_header HashStyle LGPLv2;
7794
7795   pr "\
7796 u\"\"\"Python bindings for libguestfs
7797
7798 import guestfs
7799 g = guestfs.GuestFS ()
7800 g.add_drive (\"guest.img\")
7801 g.launch ()
7802 g.wait_ready ()
7803 parts = g.list_partitions ()
7804
7805 The guestfs module provides a Python binding to the libguestfs API
7806 for examining and modifying virtual machine disk images.
7807
7808 Amongst the things this is good for: making batch configuration
7809 changes to guests, getting disk used/free statistics (see also:
7810 virt-df), migrating between virtualization systems (see also:
7811 virt-p2v), performing partial backups, performing partial guest
7812 clones, cloning guests and changing registry/UUID/hostname info, and
7813 much else besides.
7814
7815 Libguestfs uses Linux kernel and qemu code, and can access any type of
7816 guest filesystem that Linux and qemu can, including but not limited
7817 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7818 schemes, qcow, qcow2, vmdk.
7819
7820 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7821 LVs, what filesystem is in each LV, etc.).  It can also run commands
7822 in the context of the guest.  Also you can access filesystems over FTP.
7823
7824 Errors which happen while using the API are turned into Python
7825 RuntimeError exceptions.
7826
7827 To create a guestfs handle you usually have to perform the following
7828 sequence of calls:
7829
7830 # Create the handle, call add_drive at least once, and possibly
7831 # several times if the guest has multiple block devices:
7832 g = guestfs.GuestFS ()
7833 g.add_drive (\"guest.img\")
7834
7835 # Launch the qemu subprocess and wait for it to become ready:
7836 g.launch ()
7837 g.wait_ready ()
7838
7839 # Now you can issue commands, for example:
7840 logvols = g.lvs ()
7841
7842 \"\"\"
7843
7844 import libguestfsmod
7845
7846 class GuestFS:
7847     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7848
7849     def __init__ (self):
7850         \"\"\"Create a new libguestfs handle.\"\"\"
7851         self._o = libguestfsmod.create ()
7852
7853     def __del__ (self):
7854         libguestfsmod.close (self._o)
7855
7856 ";
7857
7858   List.iter (
7859     fun (name, style, _, flags, _, _, longdesc) ->
7860       pr "    def %s " name;
7861       generate_py_call_args ~handle:"self" (snd style);
7862       pr ":\n";
7863
7864       if not (List.mem NotInDocs flags) then (
7865         let doc = replace_str longdesc "C<guestfs_" "C<g." in
7866         let doc =
7867           match fst style with
7868           | RErr | RInt _ | RInt64 _ | RBool _
7869           | RConstOptString _ | RConstString _
7870           | RString _ | RBufferOut _ -> doc
7871           | RStringList _ ->
7872               doc ^ "\n\nThis function returns a list of strings."
7873           | RStruct (_, typ) ->
7874               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7875           | RStructList (_, typ) ->
7876               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
7877           | RHashtable _ ->
7878               doc ^ "\n\nThis function returns a dictionary." in
7879         let doc =
7880           if List.mem ProtocolLimitWarning flags then
7881             doc ^ "\n\n" ^ protocol_limit_warning
7882           else doc in
7883         let doc =
7884           if List.mem DangerWillRobinson flags then
7885             doc ^ "\n\n" ^ danger_will_robinson
7886           else doc in
7887         let doc =
7888           match deprecation_notice flags with
7889           | None -> doc
7890           | Some txt -> doc ^ "\n\n" ^ txt in
7891         let doc = pod2text ~width:60 name doc in
7892         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
7893         let doc = String.concat "\n        " doc in
7894         pr "        u\"\"\"%s\"\"\"\n" doc;
7895       );
7896       pr "        return libguestfsmod.%s " name;
7897       generate_py_call_args ~handle:"self._o" (snd style);
7898       pr "\n";
7899       pr "\n";
7900   ) all_functions
7901
7902 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
7903 and generate_py_call_args ~handle args =
7904   pr "(%s" handle;
7905   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
7906   pr ")"
7907
7908 (* Useful if you need the longdesc POD text as plain text.  Returns a
7909  * list of lines.
7910  *
7911  * Because this is very slow (the slowest part of autogeneration),
7912  * we memoize the results.
7913  *)
7914 and pod2text ~width name longdesc =
7915   let key = width, name, longdesc in
7916   try Hashtbl.find pod2text_memo key
7917   with Not_found ->
7918     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
7919     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
7920     close_out chan;
7921     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
7922     let chan = Unix.open_process_in cmd in
7923     let lines = ref [] in
7924     let rec loop i =
7925       let line = input_line chan in
7926       if i = 1 then             (* discard the first line of output *)
7927         loop (i+1)
7928       else (
7929         let line = triml line in
7930         lines := line :: !lines;
7931         loop (i+1)
7932       ) in
7933     let lines = try loop 1 with End_of_file -> List.rev !lines in
7934     Unix.unlink filename;
7935     (match Unix.close_process_in chan with
7936      | Unix.WEXITED 0 -> ()
7937      | Unix.WEXITED i ->
7938          failwithf "pod2text: process exited with non-zero status (%d)" i
7939      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
7940          failwithf "pod2text: process signalled or stopped by signal %d" i
7941     );
7942     Hashtbl.add pod2text_memo key lines;
7943     let chan = open_out pod2text_memo_filename in
7944     output_value chan pod2text_memo;
7945     close_out chan;
7946     lines
7947
7948 (* Generate ruby bindings. *)
7949 and generate_ruby_c () =
7950   generate_header CStyle LGPLv2;
7951
7952   pr "\
7953 #include <stdio.h>
7954 #include <stdlib.h>
7955
7956 #include <ruby.h>
7957
7958 #include \"guestfs.h\"
7959
7960 #include \"extconf.h\"
7961
7962 /* For Ruby < 1.9 */
7963 #ifndef RARRAY_LEN
7964 #define RARRAY_LEN(r) (RARRAY((r))->len)
7965 #endif
7966
7967 static VALUE m_guestfs;                 /* guestfs module */
7968 static VALUE c_guestfs;                 /* guestfs_h handle */
7969 static VALUE e_Error;                   /* used for all errors */
7970
7971 static void ruby_guestfs_free (void *p)
7972 {
7973   if (!p) return;
7974   guestfs_close ((guestfs_h *) p);
7975 }
7976
7977 static VALUE ruby_guestfs_create (VALUE m)
7978 {
7979   guestfs_h *g;
7980
7981   g = guestfs_create ();
7982   if (!g)
7983     rb_raise (e_Error, \"failed to create guestfs handle\");
7984
7985   /* Don't print error messages to stderr by default. */
7986   guestfs_set_error_handler (g, NULL, NULL);
7987
7988   /* Wrap it, and make sure the close function is called when the
7989    * handle goes away.
7990    */
7991   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
7992 }
7993
7994 static VALUE ruby_guestfs_close (VALUE gv)
7995 {
7996   guestfs_h *g;
7997   Data_Get_Struct (gv, guestfs_h, g);
7998
7999   ruby_guestfs_free (g);
8000   DATA_PTR (gv) = NULL;
8001
8002   return Qnil;
8003 }
8004
8005 ";
8006
8007   List.iter (
8008     fun (name, style, _, _, _, _, _) ->
8009       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8010       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8011       pr ")\n";
8012       pr "{\n";
8013       pr "  guestfs_h *g;\n";
8014       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8015       pr "  if (!g)\n";
8016       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8017         name;
8018       pr "\n";
8019
8020       List.iter (
8021         function
8022         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8023             pr "  Check_Type (%sv, T_STRING);\n" n;
8024             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8025             pr "  if (!%s)\n" n;
8026             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8027             pr "              \"%s\", \"%s\");\n" n name
8028         | OptString n ->
8029             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8030         | StringList n ->
8031             pr "  char **%s;\n" n;
8032             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8033             pr "  {\n";
8034             pr "    int i, len;\n";
8035             pr "    len = RARRAY_LEN (%sv);\n" n;
8036             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8037               n;
8038             pr "    for (i = 0; i < len; ++i) {\n";
8039             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8040             pr "      %s[i] = StringValueCStr (v);\n" n;
8041             pr "    }\n";
8042             pr "    %s[len] = NULL;\n" n;
8043             pr "  }\n";
8044         | Bool n ->
8045             pr "  int %s = RTEST (%sv);\n" n n
8046         | Int n ->
8047             pr "  int %s = NUM2INT (%sv);\n" n n
8048       ) (snd style);
8049       pr "\n";
8050
8051       let error_code =
8052         match fst style with
8053         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8054         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8055         | RConstString _ | RConstOptString _ ->
8056             pr "  const char *r;\n"; "NULL"
8057         | RString _ -> pr "  char *r;\n"; "NULL"
8058         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8059         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8060         | RStructList (_, typ) ->
8061             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8062         | RBufferOut _ ->
8063             pr "  char *r;\n";
8064             pr "  size_t size;\n";
8065             "NULL" in
8066       pr "\n";
8067
8068       pr "  r = guestfs_%s " name;
8069       generate_c_call_args ~handle:"g" style;
8070       pr ";\n";
8071
8072       List.iter (
8073         function
8074         | Pathname _ | Device _ | Dev_or_Path _ | String _
8075         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8076         | StringList n ->
8077             pr "  free (%s);\n" n
8078       ) (snd style);
8079
8080       pr "  if (r == %s)\n" error_code;
8081       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8082       pr "\n";
8083
8084       (match fst style with
8085        | RErr ->
8086            pr "  return Qnil;\n"
8087        | RInt _ | RBool _ ->
8088            pr "  return INT2NUM (r);\n"
8089        | RInt64 _ ->
8090            pr "  return ULL2NUM (r);\n"
8091        | RConstString _ ->
8092            pr "  return rb_str_new2 (r);\n";
8093        | RConstOptString _ ->
8094            pr "  if (r)\n";
8095            pr "    return rb_str_new2 (r);\n";
8096            pr "  else\n";
8097            pr "    return Qnil;\n";
8098        | RString _ ->
8099            pr "  VALUE rv = rb_str_new2 (r);\n";
8100            pr "  free (r);\n";
8101            pr "  return rv;\n";
8102        | RStringList _ ->
8103            pr "  int i, len = 0;\n";
8104            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8105            pr "  VALUE rv = rb_ary_new2 (len);\n";
8106            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8107            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8108            pr "    free (r[i]);\n";
8109            pr "  }\n";
8110            pr "  free (r);\n";
8111            pr "  return rv;\n"
8112        | RStruct (_, typ) ->
8113            let cols = cols_of_struct typ in
8114            generate_ruby_struct_code typ cols
8115        | RStructList (_, typ) ->
8116            let cols = cols_of_struct typ in
8117            generate_ruby_struct_list_code typ cols
8118        | RHashtable _ ->
8119            pr "  VALUE rv = rb_hash_new ();\n";
8120            pr "  int i;\n";
8121            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8122            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8123            pr "    free (r[i]);\n";
8124            pr "    free (r[i+1]);\n";
8125            pr "  }\n";
8126            pr "  free (r);\n";
8127            pr "  return rv;\n"
8128        | RBufferOut _ ->
8129            pr "  VALUE rv = rb_str_new (r, size);\n";
8130            pr "  free (r);\n";
8131            pr "  return rv;\n";
8132       );
8133
8134       pr "}\n";
8135       pr "\n"
8136   ) all_functions;
8137
8138   pr "\
8139 /* Initialize the module. */
8140 void Init__guestfs ()
8141 {
8142   m_guestfs = rb_define_module (\"Guestfs\");
8143   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8144   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8145
8146   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8147   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8148
8149 ";
8150   (* Define the rest of the methods. *)
8151   List.iter (
8152     fun (name, style, _, _, _, _, _) ->
8153       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8154       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8155   ) all_functions;
8156
8157   pr "}\n"
8158
8159 (* Ruby code to return a struct. *)
8160 and generate_ruby_struct_code typ cols =
8161   pr "  VALUE rv = rb_hash_new ();\n";
8162   List.iter (
8163     function
8164     | name, FString ->
8165         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8166     | name, FBuffer ->
8167         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8168     | name, FUUID ->
8169         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8170     | name, (FBytes|FUInt64) ->
8171         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8172     | name, FInt64 ->
8173         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8174     | name, FUInt32 ->
8175         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8176     | name, FInt32 ->
8177         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8178     | name, FOptPercent ->
8179         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8180     | name, FChar -> (* XXX wrong? *)
8181         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8182   ) cols;
8183   pr "  guestfs_free_%s (r);\n" typ;
8184   pr "  return rv;\n"
8185
8186 (* Ruby code to return a struct list. *)
8187 and generate_ruby_struct_list_code typ cols =
8188   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8189   pr "  int i;\n";
8190   pr "  for (i = 0; i < r->len; ++i) {\n";
8191   pr "    VALUE hv = rb_hash_new ();\n";
8192   List.iter (
8193     function
8194     | name, FString ->
8195         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8196     | name, FBuffer ->
8197         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, r->val[i].%s_len));\n" name name name
8198     | name, FUUID ->
8199         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8200     | name, (FBytes|FUInt64) ->
8201         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8202     | name, FInt64 ->
8203         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8204     | name, FUInt32 ->
8205         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8206     | name, FInt32 ->
8207         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8208     | name, FOptPercent ->
8209         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8210     | name, FChar -> (* XXX wrong? *)
8211         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8212   ) cols;
8213   pr "    rb_ary_push (rv, hv);\n";
8214   pr "  }\n";
8215   pr "  guestfs_free_%s_list (r);\n" typ;
8216   pr "  return rv;\n"
8217
8218 (* Generate Java bindings GuestFS.java file. *)
8219 and generate_java_java () =
8220   generate_header CStyle LGPLv2;
8221
8222   pr "\
8223 package com.redhat.et.libguestfs;
8224
8225 import java.util.HashMap;
8226 import com.redhat.et.libguestfs.LibGuestFSException;
8227 import com.redhat.et.libguestfs.PV;
8228 import com.redhat.et.libguestfs.VG;
8229 import com.redhat.et.libguestfs.LV;
8230 import com.redhat.et.libguestfs.Stat;
8231 import com.redhat.et.libguestfs.StatVFS;
8232 import com.redhat.et.libguestfs.IntBool;
8233 import com.redhat.et.libguestfs.Dirent;
8234
8235 /**
8236  * The GuestFS object is a libguestfs handle.
8237  *
8238  * @author rjones
8239  */
8240 public class GuestFS {
8241   // Load the native code.
8242   static {
8243     System.loadLibrary (\"guestfs_jni\");
8244   }
8245
8246   /**
8247    * The native guestfs_h pointer.
8248    */
8249   long g;
8250
8251   /**
8252    * Create a libguestfs handle.
8253    *
8254    * @throws LibGuestFSException
8255    */
8256   public GuestFS () throws LibGuestFSException
8257   {
8258     g = _create ();
8259   }
8260   private native long _create () throws LibGuestFSException;
8261
8262   /**
8263    * Close a libguestfs handle.
8264    *
8265    * You can also leave handles to be collected by the garbage
8266    * collector, but this method ensures that the resources used
8267    * by the handle are freed up immediately.  If you call any
8268    * other methods after closing the handle, you will get an
8269    * exception.
8270    *
8271    * @throws LibGuestFSException
8272    */
8273   public void close () throws LibGuestFSException
8274   {
8275     if (g != 0)
8276       _close (g);
8277     g = 0;
8278   }
8279   private native void _close (long g) throws LibGuestFSException;
8280
8281   public void finalize () throws LibGuestFSException
8282   {
8283     close ();
8284   }
8285
8286 ";
8287
8288   List.iter (
8289     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8290       if not (List.mem NotInDocs flags); then (
8291         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8292         let doc =
8293           if List.mem ProtocolLimitWarning flags then
8294             doc ^ "\n\n" ^ protocol_limit_warning
8295           else doc in
8296         let doc =
8297           if List.mem DangerWillRobinson flags then
8298             doc ^ "\n\n" ^ danger_will_robinson
8299           else doc in
8300         let doc =
8301           match deprecation_notice flags with
8302           | None -> doc
8303           | Some txt -> doc ^ "\n\n" ^ txt in
8304         let doc = pod2text ~width:60 name doc in
8305         let doc = List.map (            (* RHBZ#501883 *)
8306           function
8307           | "" -> "<p>"
8308           | nonempty -> nonempty
8309         ) doc in
8310         let doc = String.concat "\n   * " doc in
8311
8312         pr "  /**\n";
8313         pr "   * %s\n" shortdesc;
8314         pr "   * <p>\n";
8315         pr "   * %s\n" doc;
8316         pr "   * @throws LibGuestFSException\n";
8317         pr "   */\n";
8318         pr "  ";
8319       );
8320       generate_java_prototype ~public:true ~semicolon:false name style;
8321       pr "\n";
8322       pr "  {\n";
8323       pr "    if (g == 0)\n";
8324       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8325         name;
8326       pr "    ";
8327       if fst style <> RErr then pr "return ";
8328       pr "_%s " name;
8329       generate_java_call_args ~handle:"g" (snd style);
8330       pr ";\n";
8331       pr "  }\n";
8332       pr "  ";
8333       generate_java_prototype ~privat:true ~native:true name style;
8334       pr "\n";
8335       pr "\n";
8336   ) all_functions;
8337
8338   pr "}\n"
8339
8340 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8341 and generate_java_call_args ~handle args =
8342   pr "(%s" handle;
8343   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8344   pr ")"
8345
8346 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8347     ?(semicolon=true) name style =
8348   if privat then pr "private ";
8349   if public then pr "public ";
8350   if native then pr "native ";
8351
8352   (* return type *)
8353   (match fst style with
8354    | RErr -> pr "void ";
8355    | RInt _ -> pr "int ";
8356    | RInt64 _ -> pr "long ";
8357    | RBool _ -> pr "boolean ";
8358    | RConstString _ | RConstOptString _ | RString _
8359    | RBufferOut _ -> pr "String ";
8360    | RStringList _ -> pr "String[] ";
8361    | RStruct (_, typ) ->
8362        let name = java_name_of_struct typ in
8363        pr "%s " name;
8364    | RStructList (_, typ) ->
8365        let name = java_name_of_struct typ in
8366        pr "%s[] " name;
8367    | RHashtable _ -> pr "HashMap<String,String> ";
8368   );
8369
8370   if native then pr "_%s " name else pr "%s " name;
8371   pr "(";
8372   let needs_comma = ref false in
8373   if native then (
8374     pr "long g";
8375     needs_comma := true
8376   );
8377
8378   (* args *)
8379   List.iter (
8380     fun arg ->
8381       if !needs_comma then pr ", ";
8382       needs_comma := true;
8383
8384       match arg with
8385       | Pathname n
8386       | Device n | Dev_or_Path n
8387       | String n
8388       | OptString n
8389       | FileIn n
8390       | FileOut n ->
8391           pr "String %s" n
8392       | StringList n ->
8393           pr "String[] %s" n
8394       | Bool n ->
8395           pr "boolean %s" n
8396       | Int n ->
8397           pr "int %s" n
8398   ) (snd style);
8399
8400   pr ")\n";
8401   pr "    throws LibGuestFSException";
8402   if semicolon then pr ";"
8403
8404 and generate_java_struct jtyp cols =
8405   generate_header CStyle LGPLv2;
8406
8407   pr "\
8408 package com.redhat.et.libguestfs;
8409
8410 /**
8411  * Libguestfs %s structure.
8412  *
8413  * @author rjones
8414  * @see GuestFS
8415  */
8416 public class %s {
8417 " jtyp jtyp;
8418
8419   List.iter (
8420     function
8421     | name, FString
8422     | name, FUUID
8423     | name, FBuffer -> pr "  public String %s;\n" name
8424     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8425     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8426     | name, FChar -> pr "  public char %s;\n" name
8427     | name, FOptPercent ->
8428         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8429         pr "  public float %s;\n" name
8430   ) cols;
8431
8432   pr "}\n"
8433
8434 and generate_java_c () =
8435   generate_header CStyle LGPLv2;
8436
8437   pr "\
8438 #include <stdio.h>
8439 #include <stdlib.h>
8440 #include <string.h>
8441
8442 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8443 #include \"guestfs.h\"
8444
8445 /* Note that this function returns.  The exception is not thrown
8446  * until after the wrapper function returns.
8447  */
8448 static void
8449 throw_exception (JNIEnv *env, const char *msg)
8450 {
8451   jclass cl;
8452   cl = (*env)->FindClass (env,
8453                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8454   (*env)->ThrowNew (env, cl, msg);
8455 }
8456
8457 JNIEXPORT jlong JNICALL
8458 Java_com_redhat_et_libguestfs_GuestFS__1create
8459   (JNIEnv *env, jobject obj)
8460 {
8461   guestfs_h *g;
8462
8463   g = guestfs_create ();
8464   if (g == NULL) {
8465     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8466     return 0;
8467   }
8468   guestfs_set_error_handler (g, NULL, NULL);
8469   return (jlong) (long) g;
8470 }
8471
8472 JNIEXPORT void JNICALL
8473 Java_com_redhat_et_libguestfs_GuestFS__1close
8474   (JNIEnv *env, jobject obj, jlong jg)
8475 {
8476   guestfs_h *g = (guestfs_h *) (long) jg;
8477   guestfs_close (g);
8478 }
8479
8480 ";
8481
8482   List.iter (
8483     fun (name, style, _, _, _, _, _) ->
8484       pr "JNIEXPORT ";
8485       (match fst style with
8486        | RErr -> pr "void ";
8487        | RInt _ -> pr "jint ";
8488        | RInt64 _ -> pr "jlong ";
8489        | RBool _ -> pr "jboolean ";
8490        | RConstString _ | RConstOptString _ | RString _
8491        | RBufferOut _ -> pr "jstring ";
8492        | RStruct _ | RHashtable _ ->
8493            pr "jobject ";
8494        | RStringList _ | RStructList _ ->
8495            pr "jobjectArray ";
8496       );
8497       pr "JNICALL\n";
8498       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8499       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8500       pr "\n";
8501       pr "  (JNIEnv *env, jobject obj, jlong jg";
8502       List.iter (
8503         function
8504         | Pathname n
8505         | Device n | Dev_or_Path n
8506         | String n
8507         | OptString n
8508         | FileIn n
8509         | FileOut n ->
8510             pr ", jstring j%s" n
8511         | StringList n ->
8512             pr ", jobjectArray j%s" n
8513         | Bool n ->
8514             pr ", jboolean j%s" n
8515         | Int n ->
8516             pr ", jint j%s" n
8517       ) (snd style);
8518       pr ")\n";
8519       pr "{\n";
8520       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8521       let error_code, no_ret =
8522         match fst style with
8523         | RErr -> pr "  int r;\n"; "-1", ""
8524         | RBool _
8525         | RInt _ -> pr "  int r;\n"; "-1", "0"
8526         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8527         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8528         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8529         | RString _ ->
8530             pr "  jstring jr;\n";
8531             pr "  char *r;\n"; "NULL", "NULL"
8532         | RStringList _ ->
8533             pr "  jobjectArray jr;\n";
8534             pr "  int r_len;\n";
8535             pr "  jclass cl;\n";
8536             pr "  jstring jstr;\n";
8537             pr "  char **r;\n"; "NULL", "NULL"
8538         | RStruct (_, typ) ->
8539             pr "  jobject jr;\n";
8540             pr "  jclass cl;\n";
8541             pr "  jfieldID fl;\n";
8542             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8543         | RStructList (_, typ) ->
8544             pr "  jobjectArray jr;\n";
8545             pr "  jclass cl;\n";
8546             pr "  jfieldID fl;\n";
8547             pr "  jobject jfl;\n";
8548             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8549         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8550         | RBufferOut _ ->
8551             pr "  jstring jr;\n";
8552             pr "  char *r;\n";
8553             pr "  size_t size;\n";
8554             "NULL", "NULL" in
8555       List.iter (
8556         function
8557         | Pathname n
8558         | Device n | Dev_or_Path n
8559         | String n
8560         | OptString n
8561         | FileIn n
8562         | FileOut n ->
8563             pr "  const char *%s;\n" n
8564         | StringList n ->
8565             pr "  int %s_len;\n" n;
8566             pr "  const char **%s;\n" n
8567         | Bool n
8568         | Int n ->
8569             pr "  int %s;\n" n
8570       ) (snd style);
8571
8572       let needs_i =
8573         (match fst style with
8574          | RStringList _ | RStructList _ -> true
8575          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8576          | RConstOptString _
8577          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8578           List.exists (function StringList _ -> true | _ -> false) (snd style) in
8579       if needs_i then
8580         pr "  int i;\n";
8581
8582       pr "\n";
8583
8584       (* Get the parameters. *)
8585       List.iter (
8586         function
8587         | Pathname n
8588         | Device n | Dev_or_Path n
8589         | String n
8590         | FileIn n
8591         | FileOut n ->
8592             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8593         | OptString n ->
8594             (* This is completely undocumented, but Java null becomes
8595              * a NULL parameter.
8596              *)
8597             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8598         | StringList n ->
8599             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8600             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8601             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8602             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8603               n;
8604             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8605             pr "  }\n";
8606             pr "  %s[%s_len] = NULL;\n" n n;
8607         | Bool n
8608         | Int n ->
8609             pr "  %s = j%s;\n" n n
8610       ) (snd style);
8611
8612       (* Make the call. *)
8613       pr "  r = guestfs_%s " name;
8614       generate_c_call_args ~handle:"g" style;
8615       pr ";\n";
8616
8617       (* Release the parameters. *)
8618       List.iter (
8619         function
8620         | Pathname n
8621         | Device n | Dev_or_Path n
8622         | String n
8623         | FileIn n
8624         | FileOut n ->
8625             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8626         | OptString n ->
8627             pr "  if (j%s)\n" n;
8628             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8629         | StringList n ->
8630             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8631             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8632               n;
8633             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8634             pr "  }\n";
8635             pr "  free (%s);\n" n
8636         | Bool n
8637         | Int n -> ()
8638       ) (snd style);
8639
8640       (* Check for errors. *)
8641       pr "  if (r == %s) {\n" error_code;
8642       pr "    throw_exception (env, guestfs_last_error (g));\n";
8643       pr "    return %s;\n" no_ret;
8644       pr "  }\n";
8645
8646       (* Return value. *)
8647       (match fst style with
8648        | RErr -> ()
8649        | RInt _ -> pr "  return (jint) r;\n"
8650        | RBool _ -> pr "  return (jboolean) r;\n"
8651        | RInt64 _ -> pr "  return (jlong) r;\n"
8652        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8653        | RConstOptString _ ->
8654            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8655        | RString _ ->
8656            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8657            pr "  free (r);\n";
8658            pr "  return jr;\n"
8659        | RStringList _ ->
8660            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8661            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8662            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8663            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8664            pr "  for (i = 0; i < r_len; ++i) {\n";
8665            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8666            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8667            pr "    free (r[i]);\n";
8668            pr "  }\n";
8669            pr "  free (r);\n";
8670            pr "  return jr;\n"
8671        | RStruct (_, typ) ->
8672            let jtyp = java_name_of_struct typ in
8673            let cols = cols_of_struct typ in
8674            generate_java_struct_return typ jtyp cols
8675        | RStructList (_, typ) ->
8676            let jtyp = java_name_of_struct typ in
8677            let cols = cols_of_struct typ in
8678            generate_java_struct_list_return typ jtyp cols
8679        | RHashtable _ ->
8680            (* XXX *)
8681            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8682            pr "  return NULL;\n"
8683        | RBufferOut _ ->
8684            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8685            pr "  free (r);\n";
8686            pr "  return jr;\n"
8687       );
8688
8689       pr "}\n";
8690       pr "\n"
8691   ) all_functions
8692
8693 and generate_java_struct_return typ jtyp cols =
8694   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8695   pr "  jr = (*env)->AllocObject (env, cl);\n";
8696   List.iter (
8697     function
8698     | name, FString ->
8699         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8700         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8701     | name, FUUID ->
8702         pr "  {\n";
8703         pr "    char s[33];\n";
8704         pr "    memcpy (s, r->%s, 32);\n" name;
8705         pr "    s[32] = 0;\n";
8706         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8707         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8708         pr "  }\n";
8709     | name, FBuffer ->
8710         pr "  {\n";
8711         pr "    int len = r->%s_len;\n" name;
8712         pr "    char s[len+1];\n";
8713         pr "    memcpy (s, r->%s, len);\n" name;
8714         pr "    s[len] = 0;\n";
8715         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8716         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8717         pr "  }\n";
8718     | name, (FBytes|FUInt64|FInt64) ->
8719         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8720         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8721     | name, (FUInt32|FInt32) ->
8722         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8723         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8724     | name, FOptPercent ->
8725         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8726         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8727     | name, FChar ->
8728         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8729         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8730   ) cols;
8731   pr "  free (r);\n";
8732   pr "  return jr;\n"
8733
8734 and generate_java_struct_list_return typ jtyp cols =
8735   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8736   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8737   pr "  for (i = 0; i < r->len; ++i) {\n";
8738   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8739   List.iter (
8740     function
8741     | name, FString ->
8742         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8743         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8744     | name, FUUID ->
8745         pr "    {\n";
8746         pr "      char s[33];\n";
8747         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8748         pr "      s[32] = 0;\n";
8749         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8750         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8751         pr "    }\n";
8752     | name, FBuffer ->
8753         pr "    {\n";
8754         pr "      int len = r->val[i].%s_len;\n" name;
8755         pr "      char s[len+1];\n";
8756         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8757         pr "      s[len] = 0;\n";
8758         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8759         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8760         pr "    }\n";
8761     | name, (FBytes|FUInt64|FInt64) ->
8762         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8763         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8764     | name, (FUInt32|FInt32) ->
8765         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8766         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8767     | name, FOptPercent ->
8768         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8769         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8770     | name, FChar ->
8771         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8772         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8773   ) cols;
8774   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8775   pr "  }\n";
8776   pr "  guestfs_free_%s_list (r);\n" typ;
8777   pr "  return jr;\n"
8778
8779 and generate_java_makefile_inc () =
8780   generate_header HashStyle GPLv2;
8781
8782   pr "java_built_sources = \\\n";
8783   List.iter (
8784     fun (typ, jtyp) ->
8785         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8786   ) java_structs;
8787   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8788
8789 and generate_haskell_hs () =
8790   generate_header HaskellStyle LGPLv2;
8791
8792   (* XXX We only know how to generate partial FFI for Haskell
8793    * at the moment.  Please help out!
8794    *)
8795   let can_generate style =
8796     match style with
8797     | RErr, _
8798     | RInt _, _
8799     | RInt64 _, _ -> true
8800     | RBool _, _
8801     | RConstString _, _
8802     | RConstOptString _, _
8803     | RString _, _
8804     | RStringList _, _
8805     | RStruct _, _
8806     | RStructList _, _
8807     | RHashtable _, _
8808     | RBufferOut _, _ -> false in
8809
8810   pr "\
8811 {-# INCLUDE <guestfs.h> #-}
8812 {-# LANGUAGE ForeignFunctionInterface #-}
8813
8814 module Guestfs (
8815   create";
8816
8817   (* List out the names of the actions we want to export. *)
8818   List.iter (
8819     fun (name, style, _, _, _, _, _) ->
8820       if can_generate style then pr ",\n  %s" name
8821   ) all_functions;
8822
8823   pr "
8824   ) where
8825 import Foreign
8826 import Foreign.C
8827 import Foreign.C.Types
8828 import IO
8829 import Control.Exception
8830 import Data.Typeable
8831
8832 data GuestfsS = GuestfsS            -- represents the opaque C struct
8833 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
8834 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8835
8836 -- XXX define properly later XXX
8837 data PV = PV
8838 data VG = VG
8839 data LV = LV
8840 data IntBool = IntBool
8841 data Stat = Stat
8842 data StatVFS = StatVFS
8843 data Hashtable = Hashtable
8844
8845 foreign import ccall unsafe \"guestfs_create\" c_create
8846   :: IO GuestfsP
8847 foreign import ccall unsafe \"&guestfs_close\" c_close
8848   :: FunPtr (GuestfsP -> IO ())
8849 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8850   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8851
8852 create :: IO GuestfsH
8853 create = do
8854   p <- c_create
8855   c_set_error_handler p nullPtr nullPtr
8856   h <- newForeignPtr c_close p
8857   return h
8858
8859 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8860   :: GuestfsP -> IO CString
8861
8862 -- last_error :: GuestfsH -> IO (Maybe String)
8863 -- last_error h = do
8864 --   str <- withForeignPtr h (\\p -> c_last_error p)
8865 --   maybePeek peekCString str
8866
8867 last_error :: GuestfsH -> IO (String)
8868 last_error h = do
8869   str <- withForeignPtr h (\\p -> c_last_error p)
8870   if (str == nullPtr)
8871     then return \"no error\"
8872     else peekCString str
8873
8874 ";
8875
8876   (* Generate wrappers for each foreign function. *)
8877   List.iter (
8878     fun (name, style, _, _, _, _, _) ->
8879       if can_generate style then (
8880         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8881         pr "  :: ";
8882         generate_haskell_prototype ~handle:"GuestfsP" style;
8883         pr "\n";
8884         pr "\n";
8885         pr "%s :: " name;
8886         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
8887         pr "\n";
8888         pr "%s %s = do\n" name
8889           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
8890         pr "  r <- ";
8891         (* Convert pointer arguments using with* functions. *)
8892         List.iter (
8893           function
8894           | FileIn n
8895           | FileOut n
8896           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
8897           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
8898           | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
8899           | Bool _ | Int _ -> ()
8900         ) (snd style);
8901         (* Convert integer arguments. *)
8902         let args =
8903           List.map (
8904             function
8905             | Bool n -> sprintf "(fromBool %s)" n
8906             | Int n -> sprintf "(fromIntegral %s)" n
8907             | FileIn n | FileOut n
8908             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n -> n
8909           ) (snd style) in
8910         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
8911           (String.concat " " ("p" :: args));
8912         (match fst style with
8913          | RErr | RInt _ | RInt64 _ | RBool _ ->
8914              pr "  if (r == -1)\n";
8915              pr "    then do\n";
8916              pr "      err <- last_error h\n";
8917              pr "      fail err\n";
8918          | RConstString _ | RConstOptString _ | RString _
8919          | RStringList _ | RStruct _
8920          | RStructList _ | RHashtable _ | RBufferOut _ ->
8921              pr "  if (r == nullPtr)\n";
8922              pr "    then do\n";
8923              pr "      err <- last_error h\n";
8924              pr "      fail err\n";
8925         );
8926         (match fst style with
8927          | RErr ->
8928              pr "    else return ()\n"
8929          | RInt _ ->
8930              pr "    else return (fromIntegral r)\n"
8931          | RInt64 _ ->
8932              pr "    else return (fromIntegral r)\n"
8933          | RBool _ ->
8934              pr "    else return (toBool r)\n"
8935          | RConstString _
8936          | RConstOptString _
8937          | RString _
8938          | RStringList _
8939          | RStruct _
8940          | RStructList _
8941          | RHashtable _
8942          | RBufferOut _ ->
8943              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
8944         );
8945         pr "\n";
8946       )
8947   ) all_functions
8948
8949 and generate_haskell_prototype ~handle ?(hs = false) style =
8950   pr "%s -> " handle;
8951   let string = if hs then "String" else "CString" in
8952   let int = if hs then "Int" else "CInt" in
8953   let bool = if hs then "Bool" else "CInt" in
8954   let int64 = if hs then "Integer" else "Int64" in
8955   List.iter (
8956     fun arg ->
8957       (match arg with
8958        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
8959        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
8960        | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
8961        | Bool _ -> pr "%s" bool
8962        | Int _ -> pr "%s" int
8963        | FileIn _ -> pr "%s" string
8964        | FileOut _ -> pr "%s" string
8965       );
8966       pr " -> ";
8967   ) (snd style);
8968   pr "IO (";
8969   (match fst style with
8970    | RErr -> if not hs then pr "CInt"
8971    | RInt _ -> pr "%s" int
8972    | RInt64 _ -> pr "%s" int64
8973    | RBool _ -> pr "%s" bool
8974    | RConstString _ -> pr "%s" string
8975    | RConstOptString _ -> pr "Maybe %s" string
8976    | RString _ -> pr "%s" string
8977    | RStringList _ -> pr "[%s]" string
8978    | RStruct (_, typ) ->
8979        let name = java_name_of_struct typ in
8980        pr "%s" name
8981    | RStructList (_, typ) ->
8982        let name = java_name_of_struct typ in
8983        pr "[%s]" name
8984    | RHashtable _ -> pr "Hashtable"
8985    | RBufferOut _ -> pr "%s" string
8986   );
8987   pr ")"
8988
8989 and generate_bindtests () =
8990   generate_header CStyle LGPLv2;
8991
8992   pr "\
8993 #include <stdio.h>
8994 #include <stdlib.h>
8995 #include <inttypes.h>
8996 #include <string.h>
8997
8998 #include \"guestfs.h\"
8999 #include \"guestfs_protocol.h\"
9000
9001 #define error guestfs_error
9002 #define safe_calloc guestfs_safe_calloc
9003 #define safe_malloc guestfs_safe_malloc
9004
9005 static void
9006 print_strings (char * const* const argv)
9007 {
9008   int argc;
9009
9010   printf (\"[\");
9011   for (argc = 0; argv[argc] != NULL; ++argc) {
9012     if (argc > 0) printf (\", \");
9013     printf (\"\\\"%%s\\\"\", argv[argc]);
9014   }
9015   printf (\"]\\n\");
9016 }
9017
9018 /* The test0 function prints its parameters to stdout. */
9019 ";
9020
9021   let test0, tests =
9022     match test_functions with
9023     | [] -> assert false
9024     | test0 :: tests -> test0, tests in
9025
9026   let () =
9027     let (name, style, _, _, _, _, _) = test0 in
9028     generate_prototype ~extern:false ~semicolon:false ~newline:true
9029       ~handle:"g" ~prefix:"guestfs_" name style;
9030     pr "{\n";
9031     List.iter (
9032       function
9033       | Pathname n
9034       | Device n | Dev_or_Path n
9035       | String n
9036       | FileIn n
9037       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9038       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9039       | StringList n -> pr "  print_strings (%s);\n" n
9040       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9041       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9042     ) (snd style);
9043     pr "  /* Java changes stdout line buffering so we need this: */\n";
9044     pr "  fflush (stdout);\n";
9045     pr "  return 0;\n";
9046     pr "}\n";
9047     pr "\n" in
9048
9049   List.iter (
9050     fun (name, style, _, _, _, _, _) ->
9051       if String.sub name (String.length name - 3) 3 <> "err" then (
9052         pr "/* Test normal return. */\n";
9053         generate_prototype ~extern:false ~semicolon:false ~newline:true
9054           ~handle:"g" ~prefix:"guestfs_" name style;
9055         pr "{\n";
9056         (match fst style with
9057          | RErr ->
9058              pr "  return 0;\n"
9059          | RInt _ ->
9060              pr "  int r;\n";
9061              pr "  sscanf (val, \"%%d\", &r);\n";
9062              pr "  return r;\n"
9063          | RInt64 _ ->
9064              pr "  int64_t r;\n";
9065              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9066              pr "  return r;\n"
9067          | RBool _ ->
9068              pr "  return strcmp (val, \"true\") == 0;\n"
9069          | RConstString _
9070          | RConstOptString _ ->
9071              (* Can't return the input string here.  Return a static
9072               * string so we ensure we get a segfault if the caller
9073               * tries to free it.
9074               *)
9075              pr "  return \"static string\";\n"
9076          | RString _ ->
9077              pr "  return strdup (val);\n"
9078          | RStringList _ ->
9079              pr "  char **strs;\n";
9080              pr "  int n, i;\n";
9081              pr "  sscanf (val, \"%%d\", &n);\n";
9082              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9083              pr "  for (i = 0; i < n; ++i) {\n";
9084              pr "    strs[i] = safe_malloc (g, 16);\n";
9085              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9086              pr "  }\n";
9087              pr "  strs[n] = NULL;\n";
9088              pr "  return strs;\n"
9089          | RStruct (_, typ) ->
9090              pr "  struct guestfs_%s *r;\n" typ;
9091              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9092              pr "  return r;\n"
9093          | RStructList (_, typ) ->
9094              pr "  struct guestfs_%s_list *r;\n" typ;
9095              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9096              pr "  sscanf (val, \"%%d\", &r->len);\n";
9097              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9098              pr "  return r;\n"
9099          | RHashtable _ ->
9100              pr "  char **strs;\n";
9101              pr "  int n, i;\n";
9102              pr "  sscanf (val, \"%%d\", &n);\n";
9103              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9104              pr "  for (i = 0; i < n; ++i) {\n";
9105              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9106              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9107              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9108              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9109              pr "  }\n";
9110              pr "  strs[n*2] = NULL;\n";
9111              pr "  return strs;\n"
9112          | RBufferOut _ ->
9113              pr "  return strdup (val);\n"
9114         );
9115         pr "}\n";
9116         pr "\n"
9117       ) else (
9118         pr "/* Test error return. */\n";
9119         generate_prototype ~extern:false ~semicolon:false ~newline:true
9120           ~handle:"g" ~prefix:"guestfs_" name style;
9121         pr "{\n";
9122         pr "  error (g, \"error\");\n";
9123         (match fst style with
9124          | RErr | RInt _ | RInt64 _ | RBool _ ->
9125              pr "  return -1;\n"
9126          | RConstString _ | RConstOptString _
9127          | RString _ | RStringList _ | RStruct _
9128          | RStructList _
9129          | RHashtable _
9130          | RBufferOut _ ->
9131              pr "  return NULL;\n"
9132         );
9133         pr "}\n";
9134         pr "\n"
9135       )
9136   ) tests
9137
9138 and generate_ocaml_bindtests () =
9139   generate_header OCamlStyle GPLv2;
9140
9141   pr "\
9142 let () =
9143   let g = Guestfs.create () in
9144 ";
9145
9146   let mkargs args =
9147     String.concat " " (
9148       List.map (
9149         function
9150         | CallString s -> "\"" ^ s ^ "\""
9151         | CallOptString None -> "None"
9152         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9153         | CallStringList xs ->
9154             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9155         | CallInt i when i >= 0 -> string_of_int i
9156         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9157         | CallBool b -> string_of_bool b
9158       ) args
9159     )
9160   in
9161
9162   generate_lang_bindtests (
9163     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9164   );
9165
9166   pr "print_endline \"EOF\"\n"
9167
9168 and generate_perl_bindtests () =
9169   pr "#!/usr/bin/perl -w\n";
9170   generate_header HashStyle GPLv2;
9171
9172   pr "\
9173 use strict;
9174
9175 use Sys::Guestfs;
9176
9177 my $g = Sys::Guestfs->new ();
9178 ";
9179
9180   let mkargs args =
9181     String.concat ", " (
9182       List.map (
9183         function
9184         | CallString s -> "\"" ^ s ^ "\""
9185         | CallOptString None -> "undef"
9186         | CallOptString (Some s) -> sprintf "\"%s\"" s
9187         | CallStringList xs ->
9188             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9189         | CallInt i -> string_of_int i
9190         | CallBool b -> if b then "1" else "0"
9191       ) args
9192     )
9193   in
9194
9195   generate_lang_bindtests (
9196     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9197   );
9198
9199   pr "print \"EOF\\n\"\n"
9200
9201 and generate_python_bindtests () =
9202   generate_header HashStyle GPLv2;
9203
9204   pr "\
9205 import guestfs
9206
9207 g = guestfs.GuestFS ()
9208 ";
9209
9210   let mkargs args =
9211     String.concat ", " (
9212       List.map (
9213         function
9214         | CallString s -> "\"" ^ s ^ "\""
9215         | CallOptString None -> "None"
9216         | CallOptString (Some s) -> sprintf "\"%s\"" s
9217         | CallStringList xs ->
9218             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9219         | CallInt i -> string_of_int i
9220         | CallBool b -> if b then "1" else "0"
9221       ) args
9222     )
9223   in
9224
9225   generate_lang_bindtests (
9226     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9227   );
9228
9229   pr "print \"EOF\"\n"
9230
9231 and generate_ruby_bindtests () =
9232   generate_header HashStyle GPLv2;
9233
9234   pr "\
9235 require 'guestfs'
9236
9237 g = Guestfs::create()
9238 ";
9239
9240   let mkargs args =
9241     String.concat ", " (
9242       List.map (
9243         function
9244         | CallString s -> "\"" ^ s ^ "\""
9245         | CallOptString None -> "nil"
9246         | CallOptString (Some s) -> sprintf "\"%s\"" s
9247         | CallStringList xs ->
9248             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9249         | CallInt i -> string_of_int i
9250         | CallBool b -> string_of_bool b
9251       ) args
9252     )
9253   in
9254
9255   generate_lang_bindtests (
9256     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9257   );
9258
9259   pr "print \"EOF\\n\"\n"
9260
9261 and generate_java_bindtests () =
9262   generate_header CStyle GPLv2;
9263
9264   pr "\
9265 import com.redhat.et.libguestfs.*;
9266
9267 public class Bindtests {
9268     public static void main (String[] argv)
9269     {
9270         try {
9271             GuestFS g = new GuestFS ();
9272 ";
9273
9274   let mkargs args =
9275     String.concat ", " (
9276       List.map (
9277         function
9278         | CallString s -> "\"" ^ s ^ "\""
9279         | CallOptString None -> "null"
9280         | CallOptString (Some s) -> sprintf "\"%s\"" s
9281         | CallStringList xs ->
9282             "new String[]{" ^
9283               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9284         | CallInt i -> string_of_int i
9285         | CallBool b -> string_of_bool b
9286       ) args
9287     )
9288   in
9289
9290   generate_lang_bindtests (
9291     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9292   );
9293
9294   pr "
9295             System.out.println (\"EOF\");
9296         }
9297         catch (Exception exn) {
9298             System.err.println (exn);
9299             System.exit (1);
9300         }
9301     }
9302 }
9303 "
9304
9305 and generate_haskell_bindtests () =
9306   generate_header HaskellStyle GPLv2;
9307
9308   pr "\
9309 module Bindtests where
9310 import qualified Guestfs
9311
9312 main = do
9313   g <- Guestfs.create
9314 ";
9315
9316   let mkargs args =
9317     String.concat " " (
9318       List.map (
9319         function
9320         | CallString s -> "\"" ^ s ^ "\""
9321         | CallOptString None -> "Nothing"
9322         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9323         | CallStringList xs ->
9324             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9325         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9326         | CallInt i -> string_of_int i
9327         | CallBool true -> "True"
9328         | CallBool false -> "False"
9329       ) args
9330     )
9331   in
9332
9333   generate_lang_bindtests (
9334     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9335   );
9336
9337   pr "  putStrLn \"EOF\"\n"
9338
9339 (* Language-independent bindings tests - we do it this way to
9340  * ensure there is parity in testing bindings across all languages.
9341  *)
9342 and generate_lang_bindtests call =
9343   call "test0" [CallString "abc"; CallOptString (Some "def");
9344                 CallStringList []; CallBool false;
9345                 CallInt 0; CallString "123"; CallString "456"];
9346   call "test0" [CallString "abc"; CallOptString None;
9347                 CallStringList []; CallBool false;
9348                 CallInt 0; CallString "123"; CallString "456"];
9349   call "test0" [CallString ""; CallOptString (Some "def");
9350                 CallStringList []; CallBool false;
9351                 CallInt 0; CallString "123"; CallString "456"];
9352   call "test0" [CallString ""; CallOptString (Some "");
9353                 CallStringList []; CallBool false;
9354                 CallInt 0; CallString "123"; CallString "456"];
9355   call "test0" [CallString "abc"; CallOptString (Some "def");
9356                 CallStringList ["1"]; CallBool false;
9357                 CallInt 0; CallString "123"; CallString "456"];
9358   call "test0" [CallString "abc"; CallOptString (Some "def");
9359                 CallStringList ["1"; "2"]; CallBool false;
9360                 CallInt 0; CallString "123"; CallString "456"];
9361   call "test0" [CallString "abc"; CallOptString (Some "def");
9362                 CallStringList ["1"]; CallBool true;
9363                 CallInt 0; CallString "123"; CallString "456"];
9364   call "test0" [CallString "abc"; CallOptString (Some "def");
9365                 CallStringList ["1"]; CallBool false;
9366                 CallInt (-1); CallString "123"; CallString "456"];
9367   call "test0" [CallString "abc"; CallOptString (Some "def");
9368                 CallStringList ["1"]; CallBool false;
9369                 CallInt (-2); CallString "123"; CallString "456"];
9370   call "test0" [CallString "abc"; CallOptString (Some "def");
9371                 CallStringList ["1"]; CallBool false;
9372                 CallInt 1; CallString "123"; CallString "456"];
9373   call "test0" [CallString "abc"; CallOptString (Some "def");
9374                 CallStringList ["1"]; CallBool false;
9375                 CallInt 2; CallString "123"; CallString "456"];
9376   call "test0" [CallString "abc"; CallOptString (Some "def");
9377                 CallStringList ["1"]; CallBool false;
9378                 CallInt 4095; CallString "123"; CallString "456"];
9379   call "test0" [CallString "abc"; CallOptString (Some "def");
9380                 CallStringList ["1"]; CallBool false;
9381                 CallInt 0; CallString ""; CallString ""]
9382
9383 (* XXX Add here tests of the return and error functions. *)
9384
9385 (* This is used to generate the src/MAX_PROC_NR file which
9386  * contains the maximum procedure number, a surrogate for the
9387  * ABI version number.  See src/Makefile.am for the details.
9388  *)
9389 and generate_max_proc_nr () =
9390   let proc_nrs = List.map (
9391     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9392   ) daemon_functions in
9393
9394   let max_proc_nr = List.fold_left max 0 proc_nrs in
9395
9396   pr "%d\n" max_proc_nr
9397
9398 let output_to filename =
9399   let filename_new = filename ^ ".new" in
9400   chan := open_out filename_new;
9401   let close () =
9402     close_out !chan;
9403     chan := stdout;
9404
9405     (* Is the new file different from the current file? *)
9406     if Sys.file_exists filename && files_equal filename filename_new then
9407       Unix.unlink filename_new          (* same, so skip it *)
9408     else (
9409       (* different, overwrite old one *)
9410       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9411       Unix.rename filename_new filename;
9412       Unix.chmod filename 0o444;
9413       printf "written %s\n%!" filename;
9414     )
9415   in
9416   close
9417
9418 (* Main program. *)
9419 let () =
9420   check_functions ();
9421
9422   if not (Sys.file_exists "HACKING") then (
9423     eprintf "\
9424 You are probably running this from the wrong directory.
9425 Run it from the top source directory using the command
9426   src/generator.ml
9427 ";
9428     exit 1
9429   );
9430
9431   let close = output_to "src/guestfs_protocol.x" in
9432   generate_xdr ();
9433   close ();
9434
9435   let close = output_to "src/guestfs-structs.h" in
9436   generate_structs_h ();
9437   close ();
9438
9439   let close = output_to "src/guestfs-actions.h" in
9440   generate_actions_h ();
9441   close ();
9442
9443   let close = output_to "src/guestfs-actions.c" in
9444   generate_client_actions ();
9445   close ();
9446
9447   let close = output_to "daemon/actions.h" in
9448   generate_daemon_actions_h ();
9449   close ();
9450
9451   let close = output_to "daemon/stubs.c" in
9452   generate_daemon_actions ();
9453   close ();
9454
9455   let close = output_to "daemon/names.c" in
9456   generate_daemon_names ();
9457   close ();
9458
9459   let close = output_to "capitests/tests.c" in
9460   generate_tests ();
9461   close ();
9462
9463   let close = output_to "src/guestfs-bindtests.c" in
9464   generate_bindtests ();
9465   close ();
9466
9467   let close = output_to "fish/cmds.c" in
9468   generate_fish_cmds ();
9469   close ();
9470
9471   let close = output_to "fish/completion.c" in
9472   generate_fish_completion ();
9473   close ();
9474
9475   let close = output_to "guestfs-structs.pod" in
9476   generate_structs_pod ();
9477   close ();
9478
9479   let close = output_to "guestfs-actions.pod" in
9480   generate_actions_pod ();
9481   close ();
9482
9483   let close = output_to "guestfish-actions.pod" in
9484   generate_fish_actions_pod ();
9485   close ();
9486
9487   let close = output_to "ocaml/guestfs.mli" in
9488   generate_ocaml_mli ();
9489   close ();
9490
9491   let close = output_to "ocaml/guestfs.ml" in
9492   generate_ocaml_ml ();
9493   close ();
9494
9495   let close = output_to "ocaml/guestfs_c_actions.c" in
9496   generate_ocaml_c ();
9497   close ();
9498
9499   let close = output_to "ocaml/bindtests.ml" in
9500   generate_ocaml_bindtests ();
9501   close ();
9502
9503   let close = output_to "perl/Guestfs.xs" in
9504   generate_perl_xs ();
9505   close ();
9506
9507   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9508   generate_perl_pm ();
9509   close ();
9510
9511   let close = output_to "perl/bindtests.pl" in
9512   generate_perl_bindtests ();
9513   close ();
9514
9515   let close = output_to "python/guestfs-py.c" in
9516   generate_python_c ();
9517   close ();
9518
9519   let close = output_to "python/guestfs.py" in
9520   generate_python_py ();
9521   close ();
9522
9523   let close = output_to "python/bindtests.py" in
9524   generate_python_bindtests ();
9525   close ();
9526
9527   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9528   generate_ruby_c ();
9529   close ();
9530
9531   let close = output_to "ruby/bindtests.rb" in
9532   generate_ruby_bindtests ();
9533   close ();
9534
9535   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9536   generate_java_java ();
9537   close ();
9538
9539   List.iter (
9540     fun (typ, jtyp) ->
9541       let cols = cols_of_struct typ in
9542       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9543       let close = output_to filename in
9544       generate_java_struct jtyp cols;
9545       close ();
9546   ) java_structs;
9547
9548   let close = output_to "java/Makefile.inc" in
9549   generate_java_makefile_inc ();
9550   close ();
9551
9552   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9553   generate_java_c ();
9554   close ();
9555
9556   let close = output_to "java/Bindtests.java" in
9557   generate_java_bindtests ();
9558   close ();
9559
9560   let close = output_to "haskell/Guestfs.hs" in
9561   generate_haskell_hs ();
9562   close ();
9563
9564   let close = output_to "haskell/Bindtests.hs" in
9565   generate_haskell_bindtests ();
9566   close ();
9567
9568   let close = output_to "src/MAX_PROC_NR" in
9569   generate_max_proc_nr ();
9570   close ();
9571
9572   (* Always generate this file last, and unconditionally.  It's used
9573    * by the Makefile to know when we must re-run the generator.
9574    *)
9575   let chan = open_out "src/stamp-generator" in
9576   fprintf chan "1\n";
9577   close_out chan