51c6704bd0f1419c173fcf596ce588e53bbcd5fe
[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 ]
3479
3480 let all_functions = non_daemon_functions @ daemon_functions
3481
3482 (* In some places we want the functions to be displayed sorted
3483  * alphabetically, so this is useful:
3484  *)
3485 let all_functions_sorted =
3486   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3487                compare n1 n2) all_functions
3488
3489 (* Field types for structures. *)
3490 type field =
3491   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3492   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3493   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3494   | FUInt32
3495   | FInt32
3496   | FUInt64
3497   | FInt64
3498   | FBytes                      (* Any int measure that counts bytes. *)
3499   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3500   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3501
3502 (* Because we generate extra parsing code for LVM command line tools,
3503  * we have to pull out the LVM columns separately here.
3504  *)
3505 let lvm_pv_cols = [
3506   "pv_name", FString;
3507   "pv_uuid", FUUID;
3508   "pv_fmt", FString;
3509   "pv_size", FBytes;
3510   "dev_size", FBytes;
3511   "pv_free", FBytes;
3512   "pv_used", FBytes;
3513   "pv_attr", FString (* XXX *);
3514   "pv_pe_count", FInt64;
3515   "pv_pe_alloc_count", FInt64;
3516   "pv_tags", FString;
3517   "pe_start", FBytes;
3518   "pv_mda_count", FInt64;
3519   "pv_mda_free", FBytes;
3520   (* Not in Fedora 10:
3521      "pv_mda_size", FBytes;
3522   *)
3523 ]
3524 let lvm_vg_cols = [
3525   "vg_name", FString;
3526   "vg_uuid", FUUID;
3527   "vg_fmt", FString;
3528   "vg_attr", FString (* XXX *);
3529   "vg_size", FBytes;
3530   "vg_free", FBytes;
3531   "vg_sysid", FString;
3532   "vg_extent_size", FBytes;
3533   "vg_extent_count", FInt64;
3534   "vg_free_count", FInt64;
3535   "max_lv", FInt64;
3536   "max_pv", FInt64;
3537   "pv_count", FInt64;
3538   "lv_count", FInt64;
3539   "snap_count", FInt64;
3540   "vg_seqno", FInt64;
3541   "vg_tags", FString;
3542   "vg_mda_count", FInt64;
3543   "vg_mda_free", FBytes;
3544   (* Not in Fedora 10:
3545      "vg_mda_size", FBytes;
3546   *)
3547 ]
3548 let lvm_lv_cols = [
3549   "lv_name", FString;
3550   "lv_uuid", FUUID;
3551   "lv_attr", FString (* XXX *);
3552   "lv_major", FInt64;
3553   "lv_minor", FInt64;
3554   "lv_kernel_major", FInt64;
3555   "lv_kernel_minor", FInt64;
3556   "lv_size", FBytes;
3557   "seg_count", FInt64;
3558   "origin", FString;
3559   "snap_percent", FOptPercent;
3560   "copy_percent", FOptPercent;
3561   "move_pv", FString;
3562   "lv_tags", FString;
3563   "mirror_log", FString;
3564   "modules", FString;
3565 ]
3566
3567 (* Names and fields in all structures (in RStruct and RStructList)
3568  * that we support.
3569  *)
3570 let structs = [
3571   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3572    * not use this struct in any new code.
3573    *)
3574   "int_bool", [
3575     "i", FInt32;                (* for historical compatibility *)
3576     "b", FInt32;                (* for historical compatibility *)
3577   ];
3578
3579   (* LVM PVs, VGs, LVs. *)
3580   "lvm_pv", lvm_pv_cols;
3581   "lvm_vg", lvm_vg_cols;
3582   "lvm_lv", lvm_lv_cols;
3583
3584   (* Column names and types from stat structures.
3585    * NB. Can't use things like 'st_atime' because glibc header files
3586    * define some of these as macros.  Ugh.
3587    *)
3588   "stat", [
3589     "dev", FInt64;
3590     "ino", FInt64;
3591     "mode", FInt64;
3592     "nlink", FInt64;
3593     "uid", FInt64;
3594     "gid", FInt64;
3595     "rdev", FInt64;
3596     "size", FInt64;
3597     "blksize", FInt64;
3598     "blocks", FInt64;
3599     "atime", FInt64;
3600     "mtime", FInt64;
3601     "ctime", FInt64;
3602   ];
3603   "statvfs", [
3604     "bsize", FInt64;
3605     "frsize", FInt64;
3606     "blocks", FInt64;
3607     "bfree", FInt64;
3608     "bavail", FInt64;
3609     "files", FInt64;
3610     "ffree", FInt64;
3611     "favail", FInt64;
3612     "fsid", FInt64;
3613     "flag", FInt64;
3614     "namemax", FInt64;
3615   ];
3616
3617   (* Column names in dirent structure. *)
3618   "dirent", [
3619     "ino", FInt64;
3620     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3621     "ftyp", FChar;
3622     "name", FString;
3623   ];
3624
3625   (* Version numbers. *)
3626   "version", [
3627     "major", FInt64;
3628     "minor", FInt64;
3629     "release", FInt64;
3630     "extra", FString;
3631   ];
3632
3633   (* Extended attribute. *)
3634   "xattr", [
3635     "attrname", FString;
3636     "attrval", FBuffer;
3637   ];
3638
3639   (* Inotify events. *)
3640   "inotify_event", [
3641     "in_wd", FInt64;
3642     "in_mask", FUInt32;
3643     "in_cookie", FUInt32;
3644     "in_name", FString;
3645   ];
3646 ] (* end of structs *)
3647
3648 (* Ugh, Java has to be different ..
3649  * These names are also used by the Haskell bindings.
3650  *)
3651 let java_structs = [
3652   "int_bool", "IntBool";
3653   "lvm_pv", "PV";
3654   "lvm_vg", "VG";
3655   "lvm_lv", "LV";
3656   "stat", "Stat";
3657   "statvfs", "StatVFS";
3658   "dirent", "Dirent";
3659   "version", "Version";
3660   "xattr", "XAttr";
3661   "inotify_event", "INotifyEvent";
3662 ]
3663
3664 (* What structs are actually returned. *)
3665 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3666
3667 (* Returns a list of RStruct/RStructList structs that are returned
3668  * by any function.  Each element of returned list is a pair:
3669  *
3670  * (structname, RStructOnly)
3671  *    == there exists function which returns RStruct (_, structname)
3672  * (structname, RStructListOnly)
3673  *    == there exists function which returns RStructList (_, structname)
3674  * (structname, RStructAndList)
3675  *    == there are functions returning both RStruct (_, structname)
3676  *                                      and RStructList (_, structname)
3677  *)
3678 let rstructs_used =
3679   (* ||| is a "logical OR" for rstructs_used_t *)
3680   let (|||) a b =
3681     match a, b with
3682     | RStructAndList, _
3683     | _, RStructAndList -> RStructAndList
3684     | RStructOnly, RStructListOnly
3685     | RStructListOnly, RStructOnly -> RStructAndList
3686     | RStructOnly, RStructOnly -> RStructOnly
3687     | RStructListOnly, RStructListOnly -> RStructListOnly
3688   in
3689
3690   let h = Hashtbl.create 13 in
3691
3692   (* if elem->oldv exists, update entry using ||| operator,
3693    * else just add elem->newv to the hash
3694    *)
3695   let update elem newv =
3696     try  let oldv = Hashtbl.find h elem in
3697          Hashtbl.replace h elem (newv ||| oldv)
3698     with Not_found -> Hashtbl.add h elem newv
3699   in
3700
3701   List.iter (
3702     fun (_, style, _, _, _, _, _) ->
3703       match fst style with
3704       | RStruct (_, structname) -> update structname RStructOnly
3705       | RStructList (_, structname) -> update structname RStructListOnly
3706       | _ -> ()
3707   ) all_functions;
3708
3709   (* return key->values as a list of (key,value) *)
3710   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3711
3712 (* debug:
3713 let () =
3714   List.iter (
3715     function
3716     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3717     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3718     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3719   ) rstructs_used
3720 *)
3721
3722 (* Used for testing language bindings. *)
3723 type callt =
3724   | CallString of string
3725   | CallOptString of string option
3726   | CallStringList of string list
3727   | CallInt of int
3728   | CallBool of bool
3729
3730 (* Used to memoize the result of pod2text. *)
3731 let pod2text_memo_filename = "src/.pod2text.data"
3732 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3733   try
3734     let chan = open_in pod2text_memo_filename in
3735     let v = input_value chan in
3736     close_in chan;
3737     v
3738   with
3739     _ -> Hashtbl.create 13
3740
3741 (* Useful functions.
3742  * Note we don't want to use any external OCaml libraries which
3743  * makes this a bit harder than it should be.
3744  *)
3745 let failwithf fs = ksprintf failwith fs
3746
3747 let replace_char s c1 c2 =
3748   let s2 = String.copy s in
3749   let r = ref false in
3750   for i = 0 to String.length s2 - 1 do
3751     if String.unsafe_get s2 i = c1 then (
3752       String.unsafe_set s2 i c2;
3753       r := true
3754     )
3755   done;
3756   if not !r then s else s2
3757
3758 let isspace c =
3759   c = ' '
3760   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3761
3762 let triml ?(test = isspace) str =
3763   let i = ref 0 in
3764   let n = ref (String.length str) in
3765   while !n > 0 && test str.[!i]; do
3766     decr n;
3767     incr i
3768   done;
3769   if !i = 0 then str
3770   else String.sub str !i !n
3771
3772 let trimr ?(test = isspace) str =
3773   let n = ref (String.length str) in
3774   while !n > 0 && test str.[!n-1]; do
3775     decr n
3776   done;
3777   if !n = String.length str then str
3778   else String.sub str 0 !n
3779
3780 let trim ?(test = isspace) str =
3781   trimr ~test (triml ~test str)
3782
3783 let rec find s sub =
3784   let len = String.length s in
3785   let sublen = String.length sub in
3786   let rec loop i =
3787     if i <= len-sublen then (
3788       let rec loop2 j =
3789         if j < sublen then (
3790           if s.[i+j] = sub.[j] then loop2 (j+1)
3791           else -1
3792         ) else
3793           i (* found *)
3794       in
3795       let r = loop2 0 in
3796       if r = -1 then loop (i+1) else r
3797     ) else
3798       -1 (* not found *)
3799   in
3800   loop 0
3801
3802 let rec replace_str s s1 s2 =
3803   let len = String.length s in
3804   let sublen = String.length s1 in
3805   let i = find s s1 in
3806   if i = -1 then s
3807   else (
3808     let s' = String.sub s 0 i in
3809     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3810     s' ^ s2 ^ replace_str s'' s1 s2
3811   )
3812
3813 let rec string_split sep str =
3814   let len = String.length str in
3815   let seplen = String.length sep in
3816   let i = find str sep in
3817   if i = -1 then [str]
3818   else (
3819     let s' = String.sub str 0 i in
3820     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3821     s' :: string_split sep s''
3822   )
3823
3824 let files_equal n1 n2 =
3825   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
3826   match Sys.command cmd with
3827   | 0 -> true
3828   | 1 -> false
3829   | i -> failwithf "%s: failed with error code %d" cmd i
3830
3831 let rec filter_map f = function
3832   | [] -> []
3833   | x :: xs ->
3834       match f x with
3835       | Some y -> y :: filter_map f xs
3836       | None -> filter_map f xs
3837
3838 let rec find_map f = function
3839   | [] -> raise Not_found
3840   | x :: xs ->
3841       match f x with
3842       | Some y -> y
3843       | None -> find_map f xs
3844
3845 let iteri f xs =
3846   let rec loop i = function
3847     | [] -> ()
3848     | x :: xs -> f i x; loop (i+1) xs
3849   in
3850   loop 0 xs
3851
3852 let mapi f xs =
3853   let rec loop i = function
3854     | [] -> []
3855     | x :: xs -> let r = f i x in r :: loop (i+1) xs
3856   in
3857   loop 0 xs
3858
3859 let name_of_argt = function
3860   | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | Bool n | Int n
3861   | FileIn n | FileOut n -> n
3862
3863 let java_name_of_struct typ =
3864   try List.assoc typ java_structs
3865   with Not_found ->
3866     failwithf
3867       "java_name_of_struct: no java_structs entry corresponding to %s" typ
3868
3869 let cols_of_struct typ =
3870   try List.assoc typ structs
3871   with Not_found ->
3872     failwithf "cols_of_struct: unknown struct %s" typ
3873
3874 let seq_of_test = function
3875   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
3876   | TestOutputListOfDevices (s, _)
3877   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
3878   | TestOutputTrue s | TestOutputFalse s
3879   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
3880   | TestOutputStruct (s, _)
3881   | TestLastFail s -> s
3882
3883 (* Handling for function flags. *)
3884 let protocol_limit_warning =
3885   "Because of the message protocol, there is a transfer limit
3886 of somewhere between 2MB and 4MB.  To transfer large files you should use
3887 FTP."
3888
3889 let danger_will_robinson =
3890   "B<This command is dangerous.  Without careful use you
3891 can easily destroy all your data>."
3892
3893 let deprecation_notice flags =
3894   try
3895     let alt =
3896       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
3897     let txt =
3898       sprintf "This function is deprecated.
3899 In new code, use the C<%s> call instead.
3900
3901 Deprecated functions will not be removed from the API, but the
3902 fact that they are deprecated indicates that there are problems
3903 with correct use of these functions." alt in
3904     Some txt
3905   with
3906     Not_found -> None
3907
3908 (* Check function names etc. for consistency. *)
3909 let check_functions () =
3910   let contains_uppercase str =
3911     let len = String.length str in
3912     let rec loop i =
3913       if i >= len then false
3914       else (
3915         let c = str.[i] in
3916         if c >= 'A' && c <= 'Z' then true
3917         else loop (i+1)
3918       )
3919     in
3920     loop 0
3921   in
3922
3923   (* Check function names. *)
3924   List.iter (
3925     fun (name, _, _, _, _, _, _) ->
3926       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
3927         failwithf "function name %s does not need 'guestfs' prefix" name;
3928       if name = "" then
3929         failwithf "function name is empty";
3930       if name.[0] < 'a' || name.[0] > 'z' then
3931         failwithf "function name %s must start with lowercase a-z" name;
3932       if String.contains name '-' then
3933         failwithf "function name %s should not contain '-', use '_' instead."
3934           name
3935   ) all_functions;
3936
3937   (* Check function parameter/return names. *)
3938   List.iter (
3939     fun (name, style, _, _, _, _, _) ->
3940       let check_arg_ret_name n =
3941         if contains_uppercase n then
3942           failwithf "%s param/ret %s should not contain uppercase chars"
3943             name n;
3944         if String.contains n '-' || String.contains n '_' then
3945           failwithf "%s param/ret %s should not contain '-' or '_'"
3946             name n;
3947         if n = "value" then
3948           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;
3949         if n = "int" || n = "char" || n = "short" || n = "long" then
3950           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
3951         if n = "i" || n = "n" then
3952           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
3953         if n = "argv" || n = "args" then
3954           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name
3955       in
3956
3957       (match fst style with
3958        | RErr -> ()
3959        | RInt n | RInt64 n | RBool n
3960        | RConstString n | RConstOptString n | RString n
3961        | RStringList n | RStruct (n, _) | RStructList (n, _)
3962        | RHashtable n | RBufferOut n ->
3963            check_arg_ret_name n
3964       );
3965       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
3966   ) all_functions;
3967
3968   (* Check short descriptions. *)
3969   List.iter (
3970     fun (name, _, _, _, _, shortdesc, _) ->
3971       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
3972         failwithf "short description of %s should begin with lowercase." name;
3973       let c = shortdesc.[String.length shortdesc-1] in
3974       if c = '\n' || c = '.' then
3975         failwithf "short description of %s should not end with . or \\n." name
3976   ) all_functions;
3977
3978   (* Check long dscriptions. *)
3979   List.iter (
3980     fun (name, _, _, _, _, _, longdesc) ->
3981       if longdesc.[String.length longdesc-1] = '\n' then
3982         failwithf "long description of %s should not end with \\n." name
3983   ) all_functions;
3984
3985   (* Check proc_nrs. *)
3986   List.iter (
3987     fun (name, _, proc_nr, _, _, _, _) ->
3988       if proc_nr <= 0 then
3989         failwithf "daemon function %s should have proc_nr > 0" name
3990   ) daemon_functions;
3991
3992   List.iter (
3993     fun (name, _, proc_nr, _, _, _, _) ->
3994       if proc_nr <> -1 then
3995         failwithf "non-daemon function %s should have proc_nr -1" name
3996   ) non_daemon_functions;
3997
3998   let proc_nrs =
3999     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4000       daemon_functions in
4001   let proc_nrs =
4002     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4003   let rec loop = function
4004     | [] -> ()
4005     | [_] -> ()
4006     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4007         loop rest
4008     | (name1,nr1) :: (name2,nr2) :: _ ->
4009         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4010           name1 name2 nr1 nr2
4011   in
4012   loop proc_nrs;
4013
4014   (* Check tests. *)
4015   List.iter (
4016     function
4017       (* Ignore functions that have no tests.  We generate a
4018        * warning when the user does 'make check' instead.
4019        *)
4020     | name, _, _, _, [], _, _ -> ()
4021     | name, _, _, _, tests, _, _ ->
4022         let funcs =
4023           List.map (
4024             fun (_, _, test) ->
4025               match seq_of_test test with
4026               | [] ->
4027                   failwithf "%s has a test containing an empty sequence" name
4028               | cmds -> List.map List.hd cmds
4029           ) tests in
4030         let funcs = List.flatten funcs in
4031
4032         let tested = List.mem name funcs in
4033
4034         if not tested then
4035           failwithf "function %s has tests but does not test itself" name
4036   ) all_functions
4037
4038 (* 'pr' prints to the current output file. *)
4039 let chan = ref stdout
4040 let pr fs = ksprintf (output_string !chan) fs
4041
4042 (* Generate a header block in a number of standard styles. *)
4043 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4044 type license = GPLv2 | LGPLv2
4045
4046 let generate_header comment license =
4047   let c = match comment with
4048     | CStyle ->     pr "/* "; " *"
4049     | HashStyle ->  pr "# ";  "#"
4050     | OCamlStyle -> pr "(* "; " *"
4051     | HaskellStyle -> pr "{- "; "  " in
4052   pr "libguestfs generated file\n";
4053   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4054   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4055   pr "%s\n" c;
4056   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4057   pr "%s\n" c;
4058   (match license with
4059    | GPLv2 ->
4060        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4061        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4062        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4063        pr "%s (at your option) any later version.\n" c;
4064        pr "%s\n" c;
4065        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4066        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4067        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4068        pr "%s GNU General Public License for more details.\n" c;
4069        pr "%s\n" c;
4070        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4071        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4072        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4073
4074    | LGPLv2 ->
4075        pr "%s This library is free software; you can redistribute it and/or\n" c;
4076        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4077        pr "%s License as published by the Free Software Foundation; either\n" c;
4078        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4079        pr "%s\n" c;
4080        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4081        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4082        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4083        pr "%s Lesser General Public License for more details.\n" c;
4084        pr "%s\n" c;
4085        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4086        pr "%s License along with this library; if not, write to the Free Software\n" c;
4087        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4088   );
4089   (match comment with
4090    | CStyle -> pr " */\n"
4091    | HashStyle -> ()
4092    | OCamlStyle -> pr " *)\n"
4093    | HaskellStyle -> pr "-}\n"
4094   );
4095   pr "\n"
4096
4097 (* Start of main code generation functions below this line. *)
4098
4099 (* Generate the pod documentation for the C API. *)
4100 let rec generate_actions_pod () =
4101   List.iter (
4102     fun (shortname, style, _, flags, _, _, longdesc) ->
4103       if not (List.mem NotInDocs flags) then (
4104         let name = "guestfs_" ^ shortname in
4105         pr "=head2 %s\n\n" name;
4106         pr " ";
4107         generate_prototype ~extern:false ~handle:"handle" name style;
4108         pr "\n\n";
4109         pr "%s\n\n" longdesc;
4110         (match fst style with
4111          | RErr ->
4112              pr "This function returns 0 on success or -1 on error.\n\n"
4113          | RInt _ ->
4114              pr "On error this function returns -1.\n\n"
4115          | RInt64 _ ->
4116              pr "On error this function returns -1.\n\n"
4117          | RBool _ ->
4118              pr "This function returns a C truth value on success or -1 on error.\n\n"
4119          | RConstString _ ->
4120              pr "This function returns a string, or NULL on error.
4121 The string is owned by the guest handle and must I<not> be freed.\n\n"
4122          | RConstOptString _ ->
4123              pr "This function returns a string which may be NULL.
4124 There is way to return an error from this function.
4125 The string is owned by the guest handle and must I<not> be freed.\n\n"
4126          | RString _ ->
4127              pr "This function returns a string, or NULL on error.
4128 I<The caller must free the returned string after use>.\n\n"
4129          | RStringList _ ->
4130              pr "This function returns a NULL-terminated array of strings
4131 (like L<environ(3)>), or NULL if there was an error.
4132 I<The caller must free the strings and the array after use>.\n\n"
4133          | RStruct (_, typ) ->
4134              pr "This function returns a C<struct guestfs_%s *>,
4135 or NULL if there was an error.
4136 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4137          | RStructList (_, typ) ->
4138              pr "This function returns a C<struct guestfs_%s_list *>
4139 (see E<lt>guestfs-structs.hE<gt>),
4140 or NULL if there was an error.
4141 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4142          | RHashtable _ ->
4143              pr "This function returns a NULL-terminated array of
4144 strings, or NULL if there was an error.
4145 The array of strings will always have length C<2n+1>, where
4146 C<n> keys and values alternate, followed by the trailing NULL entry.
4147 I<The caller must free the strings and the array after use>.\n\n"
4148          | RBufferOut _ ->
4149              pr "This function returns a buffer, or NULL on error.
4150 The size of the returned buffer is written to C<*size_r>.
4151 I<The caller must free the returned buffer after use>.\n\n"
4152         );
4153         if List.mem ProtocolLimitWarning flags then
4154           pr "%s\n\n" protocol_limit_warning;
4155         if List.mem DangerWillRobinson flags then
4156           pr "%s\n\n" danger_will_robinson;
4157         match deprecation_notice flags with
4158         | None -> ()
4159         | Some txt -> pr "%s\n\n" txt
4160       )
4161   ) all_functions_sorted
4162
4163 and generate_structs_pod () =
4164   (* Structs documentation. *)
4165   List.iter (
4166     fun (typ, cols) ->
4167       pr "=head2 guestfs_%s\n" typ;
4168       pr "\n";
4169       pr " struct guestfs_%s {\n" typ;
4170       List.iter (
4171         function
4172         | name, FChar -> pr "   char %s;\n" name
4173         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4174         | name, FInt32 -> pr "   int32_t %s;\n" name
4175         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4176         | name, FInt64 -> pr "   int64_t %s;\n" name
4177         | name, FString -> pr "   char *%s;\n" name
4178         | name, FBuffer ->
4179             pr "   /* The next two fields describe a byte array. */\n";
4180             pr "   uint32_t %s_len;\n" name;
4181             pr "   char *%s;\n" name
4182         | name, FUUID ->
4183             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4184             pr "   char %s[32];\n" name
4185         | name, FOptPercent ->
4186             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4187             pr "   float %s;\n" name
4188       ) cols;
4189       pr " };\n";
4190       pr " \n";
4191       pr " struct guestfs_%s_list {\n" typ;
4192       pr "   uint32_t len; /* Number of elements in list. */\n";
4193       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4194       pr " };\n";
4195       pr " \n";
4196       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4197       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4198         typ typ;
4199       pr "\n"
4200   ) structs
4201
4202 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4203  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4204  *
4205  * We have to use an underscore instead of a dash because otherwise
4206  * rpcgen generates incorrect code.
4207  *
4208  * This header is NOT exported to clients, but see also generate_structs_h.
4209  *)
4210 and generate_xdr () =
4211   generate_header CStyle LGPLv2;
4212
4213   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4214   pr "typedef string str<>;\n";
4215   pr "\n";
4216
4217   (* Internal structures. *)
4218   List.iter (
4219     function
4220     | typ, cols ->
4221         pr "struct guestfs_int_%s {\n" typ;
4222         List.iter (function
4223                    | name, FChar -> pr "  char %s;\n" name
4224                    | name, FString -> pr "  string %s<>;\n" name
4225                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4226                    | name, FUUID -> pr "  opaque %s[32];\n" name
4227                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4228                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4229                    | name, FOptPercent -> pr "  float %s;\n" name
4230                   ) cols;
4231         pr "};\n";
4232         pr "\n";
4233         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4234         pr "\n";
4235   ) structs;
4236
4237   List.iter (
4238     fun (shortname, style, _, _, _, _, _) ->
4239       let name = "guestfs_" ^ shortname in
4240
4241       (match snd style with
4242        | [] -> ()
4243        | args ->
4244            pr "struct %s_args {\n" name;
4245            List.iter (
4246              function
4247              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4248              | OptString n -> pr "  str *%s;\n" n
4249              | StringList n -> pr "  str %s<>;\n" n
4250              | Bool n -> pr "  bool %s;\n" n
4251              | Int n -> pr "  int %s;\n" n
4252              | FileIn _ | FileOut _ -> ()
4253            ) args;
4254            pr "};\n\n"
4255       );
4256       (match fst style with
4257        | RErr -> ()
4258        | RInt n ->
4259            pr "struct %s_ret {\n" name;
4260            pr "  int %s;\n" n;
4261            pr "};\n\n"
4262        | RInt64 n ->
4263            pr "struct %s_ret {\n" name;
4264            pr "  hyper %s;\n" n;
4265            pr "};\n\n"
4266        | RBool n ->
4267            pr "struct %s_ret {\n" name;
4268            pr "  bool %s;\n" n;
4269            pr "};\n\n"
4270        | RConstString _ | RConstOptString _ ->
4271            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4272        | RString n ->
4273            pr "struct %s_ret {\n" name;
4274            pr "  string %s<>;\n" n;
4275            pr "};\n\n"
4276        | RStringList n ->
4277            pr "struct %s_ret {\n" name;
4278            pr "  str %s<>;\n" n;
4279            pr "};\n\n"
4280        | RStruct (n, typ) ->
4281            pr "struct %s_ret {\n" name;
4282            pr "  guestfs_int_%s %s;\n" typ n;
4283            pr "};\n\n"
4284        | RStructList (n, typ) ->
4285            pr "struct %s_ret {\n" name;
4286            pr "  guestfs_int_%s_list %s;\n" typ n;
4287            pr "};\n\n"
4288        | RHashtable n ->
4289            pr "struct %s_ret {\n" name;
4290            pr "  str %s<>;\n" n;
4291            pr "};\n\n"
4292        | RBufferOut n ->
4293            pr "struct %s_ret {\n" name;
4294            pr "  opaque %s<>;\n" n;
4295            pr "};\n\n"
4296       );
4297   ) daemon_functions;
4298
4299   (* Table of procedure numbers. *)
4300   pr "enum guestfs_procedure {\n";
4301   List.iter (
4302     fun (shortname, _, proc_nr, _, _, _, _) ->
4303       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4304   ) daemon_functions;
4305   pr "  GUESTFS_PROC_NR_PROCS\n";
4306   pr "};\n";
4307   pr "\n";
4308
4309   (* Having to choose a maximum message size is annoying for several
4310    * reasons (it limits what we can do in the API), but it (a) makes
4311    * the protocol a lot simpler, and (b) provides a bound on the size
4312    * of the daemon which operates in limited memory space.  For large
4313    * file transfers you should use FTP.
4314    *)
4315   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4316   pr "\n";
4317
4318   (* Message header, etc. *)
4319   pr "\
4320 /* The communication protocol is now documented in the guestfs(3)
4321  * manpage.
4322  */
4323
4324 const GUESTFS_PROGRAM = 0x2000F5F5;
4325 const GUESTFS_PROTOCOL_VERSION = 1;
4326
4327 /* These constants must be larger than any possible message length. */
4328 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4329 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4330
4331 enum guestfs_message_direction {
4332   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4333   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4334 };
4335
4336 enum guestfs_message_status {
4337   GUESTFS_STATUS_OK = 0,
4338   GUESTFS_STATUS_ERROR = 1
4339 };
4340
4341 const GUESTFS_ERROR_LEN = 256;
4342
4343 struct guestfs_message_error {
4344   string error_message<GUESTFS_ERROR_LEN>;
4345 };
4346
4347 struct guestfs_message_header {
4348   unsigned prog;                     /* GUESTFS_PROGRAM */
4349   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4350   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4351   guestfs_message_direction direction;
4352   unsigned serial;                   /* message serial number */
4353   guestfs_message_status status;
4354 };
4355
4356 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4357
4358 struct guestfs_chunk {
4359   int cancel;                        /* if non-zero, transfer is cancelled */
4360   /* data size is 0 bytes if the transfer has finished successfully */
4361   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4362 };
4363 "
4364
4365 (* Generate the guestfs-structs.h file. *)
4366 and generate_structs_h () =
4367   generate_header CStyle LGPLv2;
4368
4369   (* This is a public exported header file containing various
4370    * structures.  The structures are carefully written to have
4371    * exactly the same in-memory format as the XDR structures that
4372    * we use on the wire to the daemon.  The reason for creating
4373    * copies of these structures here is just so we don't have to
4374    * export the whole of guestfs_protocol.h (which includes much
4375    * unrelated and XDR-dependent stuff that we don't want to be
4376    * public, or required by clients).
4377    *
4378    * To reiterate, we will pass these structures to and from the
4379    * client with a simple assignment or memcpy, so the format
4380    * must be identical to what rpcgen / the RFC defines.
4381    *)
4382
4383   (* Public structures. *)
4384   List.iter (
4385     fun (typ, cols) ->
4386       pr "struct guestfs_%s {\n" typ;
4387       List.iter (
4388         function
4389         | name, FChar -> pr "  char %s;\n" name
4390         | name, FString -> pr "  char *%s;\n" name
4391         | name, FBuffer ->
4392             pr "  uint32_t %s_len;\n" name;
4393             pr "  char *%s;\n" name
4394         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4395         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4396         | name, FInt32 -> pr "  int32_t %s;\n" name
4397         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4398         | name, FInt64 -> pr "  int64_t %s;\n" name
4399         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4400       ) cols;
4401       pr "};\n";
4402       pr "\n";
4403       pr "struct guestfs_%s_list {\n" typ;
4404       pr "  uint32_t len;\n";
4405       pr "  struct guestfs_%s *val;\n" typ;
4406       pr "};\n";
4407       pr "\n";
4408       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4409       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4410       pr "\n"
4411   ) structs
4412
4413 (* Generate the guestfs-actions.h file. *)
4414 and generate_actions_h () =
4415   generate_header CStyle LGPLv2;
4416   List.iter (
4417     fun (shortname, style, _, _, _, _, _) ->
4418       let name = "guestfs_" ^ shortname in
4419       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4420         name style
4421   ) all_functions
4422
4423 (* Generate the client-side dispatch stubs. *)
4424 and generate_client_actions () =
4425   generate_header CStyle LGPLv2;
4426
4427   pr "\
4428 #include <stdio.h>
4429 #include <stdlib.h>
4430
4431 #include \"guestfs.h\"
4432 #include \"guestfs_protocol.h\"
4433
4434 #define error guestfs_error
4435 #define perrorf guestfs_perrorf
4436 #define safe_malloc guestfs_safe_malloc
4437 #define safe_realloc guestfs_safe_realloc
4438 #define safe_strdup guestfs_safe_strdup
4439 #define safe_memdup guestfs_safe_memdup
4440
4441 /* Check the return message from a call for validity. */
4442 static int
4443 check_reply_header (guestfs_h *g,
4444                     const struct guestfs_message_header *hdr,
4445                     int proc_nr, int serial)
4446 {
4447   if (hdr->prog != GUESTFS_PROGRAM) {
4448     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4449     return -1;
4450   }
4451   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4452     error (g, \"wrong protocol version (%%d/%%d)\",
4453            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4454     return -1;
4455   }
4456   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4457     error (g, \"unexpected message direction (%%d/%%d)\",
4458            hdr->direction, GUESTFS_DIRECTION_REPLY);
4459     return -1;
4460   }
4461   if (hdr->proc != proc_nr) {
4462     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4463     return -1;
4464   }
4465   if (hdr->serial != serial) {
4466     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4467     return -1;
4468   }
4469
4470   return 0;
4471 }
4472
4473 /* Check we are in the right state to run a high-level action. */
4474 static int
4475 check_state (guestfs_h *g, const char *caller)
4476 {
4477   if (!guestfs_is_ready (g)) {
4478     if (guestfs_is_config (g))
4479       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4480         caller);
4481     else if (guestfs_is_launching (g))
4482       error (g, \"%%s: call wait_ready() before using this function\",
4483         caller);
4484     else
4485       error (g, \"%%s called from the wrong state, %%d != READY\",
4486         caller, guestfs_get_state (g));
4487     return -1;
4488   }
4489   return 0;
4490 }
4491
4492 ";
4493
4494   (* Client-side stubs for each function. *)
4495   List.iter (
4496     fun (shortname, style, _, _, _, _, _) ->
4497       let name = "guestfs_" ^ shortname in
4498
4499       (* Generate the context struct which stores the high-level
4500        * state between callback functions.
4501        *)
4502       pr "struct %s_ctx {\n" shortname;
4503       pr "  /* This flag is set by the callbacks, so we know we've done\n";
4504       pr "   * the callbacks as expected, and in the right sequence.\n";
4505       pr "   * 0 = not called, 1 = reply_cb called.\n";
4506       pr "   */\n";
4507       pr "  int cb_sequence;\n";
4508       pr "  struct guestfs_message_header hdr;\n";
4509       pr "  struct guestfs_message_error err;\n";
4510       (match fst style with
4511        | RErr -> ()
4512        | RConstString _ | RConstOptString _ ->
4513            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4514        | RInt _ | RInt64 _
4515        | RBool _ | RString _ | RStringList _
4516        | RStruct _ | RStructList _
4517        | RHashtable _ | RBufferOut _ ->
4518            pr "  struct %s_ret ret;\n" name
4519       );
4520       pr "};\n";
4521       pr "\n";
4522
4523       (* Generate the reply callback function. *)
4524       pr "static void %s_reply_cb (guestfs_h *g, void *data, XDR *xdr)\n" shortname;
4525       pr "{\n";
4526       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4527       pr "  struct %s_ctx *ctx = (struct %s_ctx *) data;\n" shortname shortname;
4528       pr "\n";
4529       pr "  /* This should definitely not happen. */\n";
4530       pr "  if (ctx->cb_sequence != 0) {\n";
4531       pr "    ctx->cb_sequence = 9999;\n";
4532       pr "    error (g, \"%%s: internal error: reply callback called twice\", \"%s\");\n" name;
4533       pr "    return;\n";
4534       pr "  }\n";
4535       pr "\n";
4536       pr "  ml->main_loop_quit (ml, g);\n";
4537       pr "\n";
4538       pr "  if (!xdr_guestfs_message_header (xdr, &ctx->hdr)) {\n";
4539       pr "    error (g, \"%%s: failed to parse reply header\", \"%s\");\n" name;
4540       pr "    return;\n";
4541       pr "  }\n";
4542       pr "  if (ctx->hdr.status == GUESTFS_STATUS_ERROR) {\n";
4543       pr "    if (!xdr_guestfs_message_error (xdr, &ctx->err)) {\n";
4544       pr "      error (g, \"%%s: failed to parse reply error\", \"%s\");\n"
4545         name;
4546       pr "      return;\n";
4547       pr "    }\n";
4548       pr "    goto done;\n";
4549       pr "  }\n";
4550
4551       (match fst style with
4552        | RErr -> ()
4553        | RConstString _ | RConstOptString _ ->
4554            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4555        | RInt _ | RInt64 _
4556        | RBool _ | RString _ | RStringList _
4557        | RStruct _ | RStructList _
4558        | RHashtable _ | RBufferOut _ ->
4559            pr "  if (!xdr_%s_ret (xdr, &ctx->ret)) {\n" name;
4560            pr "    error (g, \"%%s: failed to parse reply\", \"%s\");\n" name;
4561            pr "    return;\n";
4562            pr "  }\n";
4563       );
4564
4565       pr " done:\n";
4566       pr "  ctx->cb_sequence = 1;\n";
4567       pr "}\n\n";
4568
4569       (* Generate the action stub. *)
4570       generate_prototype ~extern:false ~semicolon:false ~newline:true
4571         ~handle:"g" name style;
4572
4573       let error_code =
4574         match fst style with
4575         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4576         | RConstString _ | RConstOptString _ ->
4577             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4578         | RString _ | RStringList _
4579         | RStruct _ | RStructList _
4580         | RHashtable _ | RBufferOut _ ->
4581             "NULL" in
4582
4583       pr "{\n";
4584
4585       (match snd style with
4586        | [] -> ()
4587        | _ -> pr "  struct %s_args args;\n" name
4588       );
4589
4590       pr "  struct %s_ctx ctx;\n" shortname;
4591       pr "  guestfs_main_loop *ml = guestfs_get_main_loop (g);\n";
4592       pr "  int serial;\n";
4593       pr "\n";
4594       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4595       pr "  guestfs_set_busy (g);\n";
4596       pr "\n";
4597       pr "  memset (&ctx, 0, sizeof ctx);\n";
4598       pr "\n";
4599
4600       (* Send the main header and arguments. *)
4601       (match snd style with
4602        | [] ->
4603            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4604              (String.uppercase shortname)
4605        | args ->
4606            List.iter (
4607              function
4608              | Pathname n | Device n | Dev_or_Path n | String n ->
4609                  pr "  args.%s = (char *) %s;\n" n n
4610              | OptString n ->
4611                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4612              | StringList n ->
4613                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4614                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4615              | Bool n ->
4616                  pr "  args.%s = %s;\n" n n
4617              | Int n ->
4618                  pr "  args.%s = %s;\n" n n
4619              | FileIn _ | FileOut _ -> ()
4620            ) args;
4621            pr "  serial = guestfs__send_sync (g, GUESTFS_PROC_%s,\n"
4622              (String.uppercase shortname);
4623            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4624              name;
4625       );
4626       pr "  if (serial == -1) {\n";
4627       pr "    guestfs_end_busy (g);\n";
4628       pr "    return %s;\n" error_code;
4629       pr "  }\n";
4630       pr "\n";
4631
4632       (* Send any additional files (FileIn) requested. *)
4633       let need_read_reply_label = ref false in
4634       List.iter (
4635         function
4636         | FileIn n ->
4637             pr "  {\n";
4638             pr "    int r;\n";
4639             pr "\n";
4640             pr "    r = guestfs__send_file_sync (g, %s);\n" n;
4641             pr "    if (r == -1) {\n";
4642             pr "      guestfs_end_busy (g);\n";
4643             pr "      return %s;\n" error_code;
4644             pr "    }\n";
4645             pr "    if (r == -2) /* daemon cancelled */\n";
4646             pr "      goto read_reply;\n";
4647             need_read_reply_label := true;
4648             pr "  }\n";
4649             pr "\n";
4650         | _ -> ()
4651       ) (snd style);
4652
4653       (* Wait for the reply from the remote end. *)
4654       if !need_read_reply_label then pr " read_reply:\n";
4655       pr "  guestfs__switch_to_receiving (g);\n";
4656       pr "  ctx.cb_sequence = 0;\n";
4657       pr "  guestfs_set_reply_callback (g, %s_reply_cb, &ctx);\n" shortname;
4658       pr "  (void) ml->main_loop_run (ml, g);\n";
4659       pr "  guestfs_set_reply_callback (g, NULL, NULL);\n";
4660       pr "  if (ctx.cb_sequence != 1) {\n";
4661       pr "    error (g, \"%%s reply failed, see earlier error messages\", \"%s\");\n" name;
4662       pr "    guestfs_end_busy (g);\n";
4663       pr "    return %s;\n" error_code;
4664       pr "  }\n";
4665       pr "\n";
4666
4667       pr "  if (check_reply_header (g, &ctx.hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4668         (String.uppercase shortname);
4669       pr "    guestfs_end_busy (g);\n";
4670       pr "    return %s;\n" error_code;
4671       pr "  }\n";
4672       pr "\n";
4673
4674       pr "  if (ctx.hdr.status == GUESTFS_STATUS_ERROR) {\n";
4675       pr "    error (g, \"%%s\", ctx.err.error_message);\n";
4676       pr "    free (ctx.err.error_message);\n";
4677       pr "    guestfs_end_busy (g);\n";
4678       pr "    return %s;\n" error_code;
4679       pr "  }\n";
4680       pr "\n";
4681
4682       (* Expecting to receive further files (FileOut)? *)
4683       List.iter (
4684         function
4685         | FileOut n ->
4686             pr "  if (guestfs__receive_file_sync (g, %s) == -1) {\n" n;
4687             pr "    guestfs_end_busy (g);\n";
4688             pr "    return %s;\n" error_code;
4689             pr "  }\n";
4690             pr "\n";
4691         | _ -> ()
4692       ) (snd style);
4693
4694       pr "  guestfs_end_busy (g);\n";
4695
4696       (match fst style with
4697        | RErr -> pr "  return 0;\n"
4698        | RInt n | RInt64 n | RBool n ->
4699            pr "  return ctx.ret.%s;\n" n
4700        | RConstString _ | RConstOptString _ ->
4701            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4702        | RString n ->
4703            pr "  return ctx.ret.%s; /* caller will free */\n" n
4704        | RStringList n | RHashtable n ->
4705            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4706            pr "  ctx.ret.%s.%s_val =\n" n n;
4707            pr "    safe_realloc (g, ctx.ret.%s.%s_val,\n" n n;
4708            pr "                  sizeof (char *) * (ctx.ret.%s.%s_len + 1));\n"
4709              n n;
4710            pr "  ctx.ret.%s.%s_val[ctx.ret.%s.%s_len] = NULL;\n" n n n n;
4711            pr "  return ctx.ret.%s.%s_val;\n" n n
4712        | RStruct (n, _) ->
4713            pr "  /* caller will free this */\n";
4714            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4715        | RStructList (n, _) ->
4716            pr "  /* caller will free this */\n";
4717            pr "  return safe_memdup (g, &ctx.ret.%s, sizeof (ctx.ret.%s));\n" n n
4718        | RBufferOut n ->
4719            pr "  *size_r = ctx.ret.%s.%s_len;\n" n n;
4720            pr "  return ctx.ret.%s.%s_val; /* caller will free */\n" n n
4721       );
4722
4723       pr "}\n\n"
4724   ) daemon_functions;
4725
4726   (* Functions to free structures. *)
4727   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4728   pr " * structure format is identical to the XDR format.  See note in\n";
4729   pr " * generator.ml.\n";
4730   pr " */\n";
4731   pr "\n";
4732
4733   List.iter (
4734     fun (typ, _) ->
4735       pr "void\n";
4736       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4737       pr "{\n";
4738       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4739       pr "  free (x);\n";
4740       pr "}\n";
4741       pr "\n";
4742
4743       pr "void\n";
4744       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4745       pr "{\n";
4746       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4747       pr "  free (x);\n";
4748       pr "}\n";
4749       pr "\n";
4750
4751   ) structs;
4752
4753 (* Generate daemon/actions.h. *)
4754 and generate_daemon_actions_h () =
4755   generate_header CStyle GPLv2;
4756
4757   pr "#include \"../src/guestfs_protocol.h\"\n";
4758   pr "\n";
4759
4760   List.iter (
4761     fun (name, style, _, _, _, _, _) ->
4762       generate_prototype
4763         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4764         name style;
4765   ) daemon_functions
4766
4767 (* Generate the server-side stubs. *)
4768 and generate_daemon_actions () =
4769   generate_header CStyle GPLv2;
4770
4771   pr "#include <config.h>\n";
4772   pr "\n";
4773   pr "#include <stdio.h>\n";
4774   pr "#include <stdlib.h>\n";
4775   pr "#include <string.h>\n";
4776   pr "#include <inttypes.h>\n";
4777   pr "#include <ctype.h>\n";
4778   pr "#include <rpc/types.h>\n";
4779   pr "#include <rpc/xdr.h>\n";
4780   pr "\n";
4781   pr "#include \"daemon.h\"\n";
4782   pr "#include \"../src/guestfs_protocol.h\"\n";
4783   pr "#include \"actions.h\"\n";
4784   pr "\n";
4785
4786   List.iter (
4787     fun (name, style, _, _, _, _, _) ->
4788       (* Generate server-side stubs. *)
4789       pr "static void %s_stub (XDR *xdr_in)\n" name;
4790       pr "{\n";
4791       let error_code =
4792         match fst style with
4793         | RErr | RInt _ -> pr "  int r;\n"; "-1"
4794         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
4795         | RBool _ -> pr "  int r;\n"; "-1"
4796         | RConstString _ | RConstOptString _ ->
4797             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4798         | RString _ -> pr "  char *r;\n"; "NULL"
4799         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
4800         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
4801         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
4802         | RBufferOut _ ->
4803             pr "  size_t size;\n";
4804             pr "  char *r;\n";
4805             "NULL" in
4806
4807       (match snd style with
4808        | [] -> ()
4809        | args ->
4810            pr "  struct guestfs_%s_args args;\n" name;
4811            List.iter (
4812              function
4813              | Device n | Dev_or_Path n
4814              | Pathname n
4815              | String n -> ()
4816              | OptString n -> pr "  char *%s;\n" n
4817              | StringList n -> pr "  char **%s;\n" n
4818              | Bool n -> pr "  int %s;\n" n
4819              | Int n -> pr "  int %s;\n" n
4820              | FileIn _ | FileOut _ -> ()
4821            ) args
4822       );
4823       pr "\n";
4824
4825       (match snd style with
4826        | [] -> ()
4827        | args ->
4828            pr "  memset (&args, 0, sizeof args);\n";
4829            pr "\n";
4830            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
4831            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
4832            pr "    return;\n";
4833            pr "  }\n";
4834            let pr_args n =
4835              pr "  char *%s = args.%s;\n" n n
4836            in
4837            List.iter (
4838              function
4839              | Pathname n ->
4840                  pr_args n;
4841                  pr "  ABS_PATH (%s, goto done);\n" n;
4842              | Device n ->
4843                  pr_args n;
4844                  pr "  RESOLVE_DEVICE (%s, goto done);" n;
4845              | Dev_or_Path n ->
4846                  pr_args n;
4847                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);" n;
4848              | String n -> pr_args n
4849              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
4850              | StringList n ->
4851                  pr "  %s = realloc (args.%s.%s_val,\n" n n n;
4852                  pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
4853                  pr "  if (%s == NULL) {\n" n;
4854                  pr "    reply_with_perror (\"realloc\");\n";
4855                  pr "    goto done;\n";
4856                  pr "  }\n";
4857                  pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
4858                  pr "  args.%s.%s_val = %s;\n" n n n;
4859              | Bool n -> pr "  %s = args.%s;\n" n n
4860              | Int n -> pr "  %s = args.%s;\n" n n
4861              | FileIn _ | FileOut _ -> ()
4862            ) args;
4863            pr "\n"
4864       );
4865
4866       (* this is used at least for do_equal *)
4867       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
4868         (* Emit NEED_ROOT just once, even when there are two or
4869            more Pathname args *)
4870         pr "  NEED_ROOT (goto done);\n";
4871       );
4872
4873       (* Don't want to call the impl with any FileIn or FileOut
4874        * parameters, since these go "outside" the RPC protocol.
4875        *)
4876       let args' =
4877         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
4878           (snd style) in
4879       pr "  r = do_%s " name;
4880       generate_c_call_args (fst style, args');
4881       pr ";\n";
4882
4883       pr "  if (r == %s)\n" error_code;
4884       pr "    /* do_%s has already called reply_with_error */\n" name;
4885       pr "    goto done;\n";
4886       pr "\n";
4887
4888       (* If there are any FileOut parameters, then the impl must
4889        * send its own reply.
4890        *)
4891       let no_reply =
4892         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
4893       if no_reply then
4894         pr "  /* do_%s has already sent a reply */\n" name
4895       else (
4896         match fst style with
4897         | RErr -> pr "  reply (NULL, NULL);\n"
4898         | RInt n | RInt64 n | RBool n ->
4899             pr "  struct guestfs_%s_ret ret;\n" name;
4900             pr "  ret.%s = r;\n" n;
4901             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4902               name
4903         | RConstString _ | RConstOptString _ ->
4904             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4905         | RString n ->
4906             pr "  struct guestfs_%s_ret ret;\n" name;
4907             pr "  ret.%s = r;\n" n;
4908             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4909               name;
4910             pr "  free (r);\n"
4911         | RStringList n | RHashtable n ->
4912             pr "  struct guestfs_%s_ret ret;\n" name;
4913             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
4914             pr "  ret.%s.%s_val = r;\n" n n;
4915             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4916               name;
4917             pr "  free_strings (r);\n"
4918         | RStruct (n, _) ->
4919             pr "  struct guestfs_%s_ret ret;\n" name;
4920             pr "  ret.%s = *r;\n" n;
4921             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4922               name;
4923             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4924               name
4925         | RStructList (n, _) ->
4926             pr "  struct guestfs_%s_ret ret;\n" name;
4927             pr "  ret.%s = *r;\n" n;
4928             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4929               name;
4930             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
4931               name
4932         | RBufferOut n ->
4933             pr "  struct guestfs_%s_ret ret;\n" name;
4934             pr "  ret.%s.%s_val = r;\n" n n;
4935             pr "  ret.%s.%s_len = size;\n" n n;
4936             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
4937               name;
4938             pr "  free (r);\n"
4939       );
4940
4941       (* Free the args. *)
4942       (match snd style with
4943        | [] ->
4944            pr "done: ;\n";
4945        | _ ->
4946            pr "done:\n";
4947            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
4948              name
4949       );
4950
4951       pr "}\n\n";
4952   ) daemon_functions;
4953
4954   (* Dispatch function. *)
4955   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
4956   pr "{\n";
4957   pr "  switch (proc_nr) {\n";
4958
4959   List.iter (
4960     fun (name, style, _, _, _, _, _) ->
4961       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
4962       pr "      %s_stub (xdr_in);\n" name;
4963       pr "      break;\n"
4964   ) daemon_functions;
4965
4966   pr "    default:\n";
4967   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";
4968   pr "  }\n";
4969   pr "}\n";
4970   pr "\n";
4971
4972   (* LVM columns and tokenization functions. *)
4973   (* XXX This generates crap code.  We should rethink how we
4974    * do this parsing.
4975    *)
4976   List.iter (
4977     function
4978     | typ, cols ->
4979         pr "static const char *lvm_%s_cols = \"%s\";\n"
4980           typ (String.concat "," (List.map fst cols));
4981         pr "\n";
4982
4983         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
4984         pr "{\n";
4985         pr "  char *tok, *p, *next;\n";
4986         pr "  int i, j;\n";
4987         pr "\n";
4988         (*
4989           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
4990           pr "\n";
4991         *)
4992         pr "  if (!str) {\n";
4993         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
4994         pr "    return -1;\n";
4995         pr "  }\n";
4996         pr "  if (!*str || isspace (*str)) {\n";
4997         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
4998         pr "    return -1;\n";
4999         pr "  }\n";
5000         pr "  tok = str;\n";
5001         List.iter (
5002           fun (name, coltype) ->
5003             pr "  if (!tok) {\n";
5004             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5005             pr "    return -1;\n";
5006             pr "  }\n";
5007             pr "  p = strchrnul (tok, ',');\n";
5008             pr "  if (*p) next = p+1; else next = NULL;\n";
5009             pr "  *p = '\\0';\n";
5010             (match coltype with
5011              | FString ->
5012                  pr "  r->%s = strdup (tok);\n" name;
5013                  pr "  if (r->%s == NULL) {\n" name;
5014                  pr "    perror (\"strdup\");\n";
5015                  pr "    return -1;\n";
5016                  pr "  }\n"
5017              | FUUID ->
5018                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5019                  pr "    if (tok[j] == '\\0') {\n";
5020                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5021                  pr "      return -1;\n";
5022                  pr "    } else if (tok[j] != '-')\n";
5023                  pr "      r->%s[i++] = tok[j];\n" name;
5024                  pr "  }\n";
5025              | FBytes ->
5026                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5027                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5028                  pr "    return -1;\n";
5029                  pr "  }\n";
5030              | FInt64 ->
5031                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5032                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5033                  pr "    return -1;\n";
5034                  pr "  }\n";
5035              | FOptPercent ->
5036                  pr "  if (tok[0] == '\\0')\n";
5037                  pr "    r->%s = -1;\n" name;
5038                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5039                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5040                  pr "    return -1;\n";
5041                  pr "  }\n";
5042              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5043                  assert false (* can never be an LVM column *)
5044             );
5045             pr "  tok = next;\n";
5046         ) cols;
5047
5048         pr "  if (tok != NULL) {\n";
5049         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5050         pr "    return -1;\n";
5051         pr "  }\n";
5052         pr "  return 0;\n";
5053         pr "}\n";
5054         pr "\n";
5055
5056         pr "guestfs_int_lvm_%s_list *\n" typ;
5057         pr "parse_command_line_%ss (void)\n" typ;
5058         pr "{\n";
5059         pr "  char *out, *err;\n";
5060         pr "  char *p, *pend;\n";
5061         pr "  int r, i;\n";
5062         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5063         pr "  void *newp;\n";
5064         pr "\n";
5065         pr "  ret = malloc (sizeof *ret);\n";
5066         pr "  if (!ret) {\n";
5067         pr "    reply_with_perror (\"malloc\");\n";
5068         pr "    return NULL;\n";
5069         pr "  }\n";
5070         pr "\n";
5071         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5072         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5073         pr "\n";
5074         pr "  r = command (&out, &err,\n";
5075         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5076         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5077         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5078         pr "  if (r == -1) {\n";
5079         pr "    reply_with_error (\"%%s\", err);\n";
5080         pr "    free (out);\n";
5081         pr "    free (err);\n";
5082         pr "    free (ret);\n";
5083         pr "    return NULL;\n";
5084         pr "  }\n";
5085         pr "\n";
5086         pr "  free (err);\n";
5087         pr "\n";
5088         pr "  /* Tokenize each line of the output. */\n";
5089         pr "  p = out;\n";
5090         pr "  i = 0;\n";
5091         pr "  while (p) {\n";
5092         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5093         pr "    if (pend) {\n";
5094         pr "      *pend = '\\0';\n";
5095         pr "      pend++;\n";
5096         pr "    }\n";
5097         pr "\n";
5098         pr "    while (*p && isspace (*p))      /* Skip any leading whitespace. */\n";
5099         pr "      p++;\n";
5100         pr "\n";
5101         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5102         pr "      p = pend;\n";
5103         pr "      continue;\n";
5104         pr "    }\n";
5105         pr "\n";
5106         pr "    /* Allocate some space to store this next entry. */\n";
5107         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5108         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5109         pr "    if (newp == NULL) {\n";
5110         pr "      reply_with_perror (\"realloc\");\n";
5111         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5112         pr "      free (ret);\n";
5113         pr "      free (out);\n";
5114         pr "      return NULL;\n";
5115         pr "    }\n";
5116         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5117         pr "\n";
5118         pr "    /* Tokenize the next entry. */\n";
5119         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5120         pr "    if (r == -1) {\n";
5121         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5122         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5123         pr "      free (ret);\n";
5124         pr "      free (out);\n";
5125         pr "      return NULL;\n";
5126         pr "    }\n";
5127         pr "\n";
5128         pr "    ++i;\n";
5129         pr "    p = pend;\n";
5130         pr "  }\n";
5131         pr "\n";
5132         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5133         pr "\n";
5134         pr "  free (out);\n";
5135         pr "  return ret;\n";
5136         pr "}\n"
5137
5138   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5139
5140 (* Generate a list of function names, for debugging in the daemon.. *)
5141 and generate_daemon_names () =
5142   generate_header CStyle GPLv2;
5143
5144   pr "#include <config.h>\n";
5145   pr "\n";
5146   pr "#include \"daemon.h\"\n";
5147   pr "\n";
5148
5149   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5150   pr "const char *function_names[] = {\n";
5151   List.iter (
5152     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5153   ) daemon_functions;
5154   pr "};\n";
5155
5156 (* Generate the tests. *)
5157 and generate_tests () =
5158   generate_header CStyle GPLv2;
5159
5160   pr "\
5161 #include <stdio.h>
5162 #include <stdlib.h>
5163 #include <string.h>
5164 #include <unistd.h>
5165 #include <sys/types.h>
5166 #include <fcntl.h>
5167
5168 #include \"guestfs.h\"
5169
5170 static guestfs_h *g;
5171 static int suppress_error = 0;
5172
5173 static void print_error (guestfs_h *g, void *data, const char *msg)
5174 {
5175   if (!suppress_error)
5176     fprintf (stderr, \"%%s\\n\", msg);
5177 }
5178
5179 static void print_strings (char * const * const argv)
5180 {
5181   int argc;
5182
5183   for (argc = 0; argv[argc] != NULL; ++argc)
5184     printf (\"\\t%%s\\n\", argv[argc]);
5185 }
5186
5187 /*
5188 static void print_table (char * const * const argv)
5189 {
5190   int i;
5191
5192   for (i = 0; argv[i] != NULL; i += 2)
5193     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5194 }
5195 */
5196
5197 ";
5198
5199   (* Generate a list of commands which are not tested anywhere. *)
5200   pr "static void no_test_warnings (void)\n";
5201   pr "{\n";
5202
5203   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5204   List.iter (
5205     fun (_, _, _, _, tests, _, _) ->
5206       let tests = filter_map (
5207         function
5208         | (_, (Always|If _|Unless _), test) -> Some test
5209         | (_, Disabled, _) -> None
5210       ) tests in
5211       let seq = List.concat (List.map seq_of_test tests) in
5212       let cmds_tested = List.map List.hd seq in
5213       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5214   ) all_functions;
5215
5216   List.iter (
5217     fun (name, _, _, _, _, _, _) ->
5218       if not (Hashtbl.mem hash name) then
5219         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5220   ) all_functions;
5221
5222   pr "}\n";
5223   pr "\n";
5224
5225   (* Generate the actual tests.  Note that we generate the tests
5226    * in reverse order, deliberately, so that (in general) the
5227    * newest tests run first.  This makes it quicker and easier to
5228    * debug them.
5229    *)
5230   let test_names =
5231     List.map (
5232       fun (name, _, _, _, tests, _, _) ->
5233         mapi (generate_one_test name) tests
5234     ) (List.rev all_functions) in
5235   let test_names = List.concat test_names in
5236   let nr_tests = List.length test_names in
5237
5238   pr "\
5239 int main (int argc, char *argv[])
5240 {
5241   char c = 0;
5242   int failed = 0;
5243   const char *filename;
5244   int fd;
5245   int nr_tests, test_num = 0;
5246
5247   setbuf (stdout, NULL);
5248
5249   no_test_warnings ();
5250
5251   g = guestfs_create ();
5252   if (g == NULL) {
5253     printf (\"guestfs_create FAILED\\n\");
5254     exit (1);
5255   }
5256
5257   guestfs_set_error_handler (g, print_error, NULL);
5258
5259   guestfs_set_path (g, \"../appliance\");
5260
5261   filename = \"test1.img\";
5262   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5263   if (fd == -1) {
5264     perror (filename);
5265     exit (1);
5266   }
5267   if (lseek (fd, %d, SEEK_SET) == -1) {
5268     perror (\"lseek\");
5269     close (fd);
5270     unlink (filename);
5271     exit (1);
5272   }
5273   if (write (fd, &c, 1) == -1) {
5274     perror (\"write\");
5275     close (fd);
5276     unlink (filename);
5277     exit (1);
5278   }
5279   if (close (fd) == -1) {
5280     perror (filename);
5281     unlink (filename);
5282     exit (1);
5283   }
5284   if (guestfs_add_drive (g, filename) == -1) {
5285     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5286     exit (1);
5287   }
5288
5289   filename = \"test2.img\";
5290   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5291   if (fd == -1) {
5292     perror (filename);
5293     exit (1);
5294   }
5295   if (lseek (fd, %d, SEEK_SET) == -1) {
5296     perror (\"lseek\");
5297     close (fd);
5298     unlink (filename);
5299     exit (1);
5300   }
5301   if (write (fd, &c, 1) == -1) {
5302     perror (\"write\");
5303     close (fd);
5304     unlink (filename);
5305     exit (1);
5306   }
5307   if (close (fd) == -1) {
5308     perror (filename);
5309     unlink (filename);
5310     exit (1);
5311   }
5312   if (guestfs_add_drive (g, filename) == -1) {
5313     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5314     exit (1);
5315   }
5316
5317   filename = \"test3.img\";
5318   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5319   if (fd == -1) {
5320     perror (filename);
5321     exit (1);
5322   }
5323   if (lseek (fd, %d, SEEK_SET) == -1) {
5324     perror (\"lseek\");
5325     close (fd);
5326     unlink (filename);
5327     exit (1);
5328   }
5329   if (write (fd, &c, 1) == -1) {
5330     perror (\"write\");
5331     close (fd);
5332     unlink (filename);
5333     exit (1);
5334   }
5335   if (close (fd) == -1) {
5336     perror (filename);
5337     unlink (filename);
5338     exit (1);
5339   }
5340   if (guestfs_add_drive (g, filename) == -1) {
5341     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5342     exit (1);
5343   }
5344
5345   if (guestfs_add_drive_ro (g, \"../images/test.sqsh\") == -1) {
5346     printf (\"guestfs_add_drive_ro ../images/test.sqsh FAILED\\n\");
5347     exit (1);
5348   }
5349
5350   if (guestfs_launch (g) == -1) {
5351     printf (\"guestfs_launch FAILED\\n\");
5352     exit (1);
5353   }
5354
5355   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5356   alarm (600);
5357
5358   if (guestfs_wait_ready (g) == -1) {
5359     printf (\"guestfs_wait_ready FAILED\\n\");
5360     exit (1);
5361   }
5362
5363   /* Cancel previous alarm. */
5364   alarm (0);
5365
5366   nr_tests = %d;
5367
5368 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5369
5370   iteri (
5371     fun i test_name ->
5372       pr "  test_num++;\n";
5373       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5374       pr "  if (%s () == -1) {\n" test_name;
5375       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5376       pr "    failed++;\n";
5377       pr "  }\n";
5378   ) test_names;
5379   pr "\n";
5380
5381   pr "  guestfs_close (g);\n";
5382   pr "  unlink (\"test1.img\");\n";
5383   pr "  unlink (\"test2.img\");\n";
5384   pr "  unlink (\"test3.img\");\n";
5385   pr "\n";
5386
5387   pr "  if (failed > 0) {\n";
5388   pr "    printf (\"***** %%d / %%d tests FAILED *****\\n\", failed, nr_tests);\n";
5389   pr "    exit (1);\n";
5390   pr "  }\n";
5391   pr "\n";
5392
5393   pr "  exit (0);\n";
5394   pr "}\n"
5395
5396 and generate_one_test name i (init, prereq, test) =
5397   let test_name = sprintf "test_%s_%d" name i in
5398
5399   pr "\
5400 static int %s_skip (void)
5401 {
5402   const char *str;
5403
5404   str = getenv (\"TEST_ONLY\");
5405   if (str)
5406     return strstr (str, \"%s\") == NULL;
5407   str = getenv (\"SKIP_%s\");
5408   if (str && strcmp (str, \"1\") == 0) return 1;
5409   str = getenv (\"SKIP_TEST_%s\");
5410   if (str && strcmp (str, \"1\") == 0) return 1;
5411   return 0;
5412 }
5413
5414 " test_name name (String.uppercase test_name) (String.uppercase name);
5415
5416   (match prereq with
5417    | Disabled | Always -> ()
5418    | If code | Unless code ->
5419        pr "static int %s_prereq (void)\n" test_name;
5420        pr "{\n";
5421        pr "  %s\n" code;
5422        pr "}\n";
5423        pr "\n";
5424   );
5425
5426   pr "\
5427 static int %s (void)
5428 {
5429   if (%s_skip ()) {
5430     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5431     return 0;
5432   }
5433
5434 " test_name test_name test_name;
5435
5436   (match prereq with
5437    | Disabled ->
5438        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5439    | If _ ->
5440        pr "  if (! %s_prereq ()) {\n" test_name;
5441        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5442        pr "    return 0;\n";
5443        pr "  }\n";
5444        pr "\n";
5445        generate_one_test_body name i test_name init test;
5446    | Unless _ ->
5447        pr "  if (%s_prereq ()) {\n" test_name;
5448        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5449        pr "    return 0;\n";
5450        pr "  }\n";
5451        pr "\n";
5452        generate_one_test_body name i test_name init test;
5453    | Always ->
5454        generate_one_test_body name i test_name init test
5455   );
5456
5457   pr "  return 0;\n";
5458   pr "}\n";
5459   pr "\n";
5460   test_name
5461
5462 and generate_one_test_body name i test_name init test =
5463   (match init with
5464    | InitNone (* XXX at some point, InitNone and InitEmpty became
5465                * folded together as the same thing.  Really we should
5466                * make InitNone do nothing at all, but the tests may
5467                * need to be checked to make sure this is OK.
5468                *)
5469    | InitEmpty ->
5470        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5471        List.iter (generate_test_command_call test_name)
5472          [["blockdev_setrw"; "/dev/sda"];
5473           ["umount_all"];
5474           ["lvm_remove_all"]]
5475    | InitPartition ->
5476        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5477        List.iter (generate_test_command_call test_name)
5478          [["blockdev_setrw"; "/dev/sda"];
5479           ["umount_all"];
5480           ["lvm_remove_all"];
5481           ["sfdiskM"; "/dev/sda"; ","]]
5482    | InitBasicFS ->
5483        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5484        List.iter (generate_test_command_call test_name)
5485          [["blockdev_setrw"; "/dev/sda"];
5486           ["umount_all"];
5487           ["lvm_remove_all"];
5488           ["sfdiskM"; "/dev/sda"; ","];
5489           ["mkfs"; "ext2"; "/dev/sda1"];
5490           ["mount"; "/dev/sda1"; "/"]]
5491    | InitBasicFSonLVM ->
5492        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5493          test_name;
5494        List.iter (generate_test_command_call test_name)
5495          [["blockdev_setrw"; "/dev/sda"];
5496           ["umount_all"];
5497           ["lvm_remove_all"];
5498           ["sfdiskM"; "/dev/sda"; ","];
5499           ["pvcreate"; "/dev/sda1"];
5500           ["vgcreate"; "VG"; "/dev/sda1"];
5501           ["lvcreate"; "LV"; "VG"; "8"];
5502           ["mkfs"; "ext2"; "/dev/VG/LV"];
5503           ["mount"; "/dev/VG/LV"; "/"]]
5504    | InitSquashFS ->
5505        pr "  /* InitSquashFS for %s */\n" test_name;
5506        List.iter (generate_test_command_call test_name)
5507          [["blockdev_setrw"; "/dev/sda"];
5508           ["umount_all"];
5509           ["lvm_remove_all"];
5510           ["mount_vfs"; "ro"; "squashfs"; "/dev/sdd"; "/"]]
5511   );
5512
5513   let get_seq_last = function
5514     | [] ->
5515         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5516           test_name
5517     | seq ->
5518         let seq = List.rev seq in
5519         List.rev (List.tl seq), List.hd seq
5520   in
5521
5522   match test with
5523   | TestRun seq ->
5524       pr "  /* TestRun for %s (%d) */\n" name i;
5525       List.iter (generate_test_command_call test_name) seq
5526   | TestOutput (seq, expected) ->
5527       pr "  /* TestOutput for %s (%d) */\n" name i;
5528       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5529       let seq, last = get_seq_last seq in
5530       let test () =
5531         pr "    if (strcmp (r, expected) != 0) {\n";
5532         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5533         pr "      return -1;\n";
5534         pr "    }\n"
5535       in
5536       List.iter (generate_test_command_call test_name) seq;
5537       generate_test_command_call ~test test_name last
5538   | TestOutputList (seq, expected) ->
5539       pr "  /* TestOutputList for %s (%d) */\n" name i;
5540       let seq, last = get_seq_last seq in
5541       let test () =
5542         iteri (
5543           fun i str ->
5544             pr "    if (!r[%d]) {\n" i;
5545             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5546             pr "      print_strings (r);\n";
5547             pr "      return -1;\n";
5548             pr "    }\n";
5549             pr "    {\n";
5550             pr "      const char *expected = \"%s\";\n" (c_quote str);
5551             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5552             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5553             pr "        return -1;\n";
5554             pr "      }\n";
5555             pr "    }\n"
5556         ) expected;
5557         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5558         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5559           test_name;
5560         pr "      print_strings (r);\n";
5561         pr "      return -1;\n";
5562         pr "    }\n"
5563       in
5564       List.iter (generate_test_command_call test_name) seq;
5565       generate_test_command_call ~test test_name last
5566   | TestOutputListOfDevices (seq, expected) ->
5567       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5568       let seq, last = get_seq_last seq in
5569       let test () =
5570         iteri (
5571           fun i str ->
5572             pr "    if (!r[%d]) {\n" i;
5573             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5574             pr "      print_strings (r);\n";
5575             pr "      return -1;\n";
5576             pr "    }\n";
5577             pr "    {\n";
5578             pr "      const char *expected = \"%s\";\n" (c_quote str);
5579             pr "      r[%d][5] = 's';\n" i;
5580             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5581             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5582             pr "        return -1;\n";
5583             pr "      }\n";
5584             pr "    }\n"
5585         ) expected;
5586         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5587         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5588           test_name;
5589         pr "      print_strings (r);\n";
5590         pr "      return -1;\n";
5591         pr "    }\n"
5592       in
5593       List.iter (generate_test_command_call test_name) seq;
5594       generate_test_command_call ~test test_name last
5595   | TestOutputInt (seq, expected) ->
5596       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5597       let seq, last = get_seq_last seq in
5598       let test () =
5599         pr "    if (r != %d) {\n" expected;
5600         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5601           test_name expected;
5602         pr "               (int) r);\n";
5603         pr "      return -1;\n";
5604         pr "    }\n"
5605       in
5606       List.iter (generate_test_command_call test_name) seq;
5607       generate_test_command_call ~test test_name last
5608   | TestOutputIntOp (seq, op, expected) ->
5609       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5610       let seq, last = get_seq_last seq in
5611       let test () =
5612         pr "    if (! (r %s %d)) {\n" op expected;
5613         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5614           test_name op expected;
5615         pr "               (int) r);\n";
5616         pr "      return -1;\n";
5617         pr "    }\n"
5618       in
5619       List.iter (generate_test_command_call test_name) seq;
5620       generate_test_command_call ~test test_name last
5621   | TestOutputTrue seq ->
5622       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5623       let seq, last = get_seq_last seq in
5624       let test () =
5625         pr "    if (!r) {\n";
5626         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5627           test_name;
5628         pr "      return -1;\n";
5629         pr "    }\n"
5630       in
5631       List.iter (generate_test_command_call test_name) seq;
5632       generate_test_command_call ~test test_name last
5633   | TestOutputFalse seq ->
5634       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5635       let seq, last = get_seq_last seq in
5636       let test () =
5637         pr "    if (r) {\n";
5638         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5639           test_name;
5640         pr "      return -1;\n";
5641         pr "    }\n"
5642       in
5643       List.iter (generate_test_command_call test_name) seq;
5644       generate_test_command_call ~test test_name last
5645   | TestOutputLength (seq, expected) ->
5646       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5647       let seq, last = get_seq_last seq in
5648       let test () =
5649         pr "    int j;\n";
5650         pr "    for (j = 0; j < %d; ++j)\n" expected;
5651         pr "      if (r[j] == NULL) {\n";
5652         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5653           test_name;
5654         pr "        print_strings (r);\n";
5655         pr "        return -1;\n";
5656         pr "      }\n";
5657         pr "    if (r[j] != NULL) {\n";
5658         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5659           test_name;
5660         pr "      print_strings (r);\n";
5661         pr "      return -1;\n";
5662         pr "    }\n"
5663       in
5664       List.iter (generate_test_command_call test_name) seq;
5665       generate_test_command_call ~test test_name last
5666   | TestOutputBuffer (seq, expected) ->
5667       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5668       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5669       let seq, last = get_seq_last seq in
5670       let len = String.length expected in
5671       let test () =
5672         pr "    if (size != %d) {\n" len;
5673         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5674         pr "      return -1;\n";
5675         pr "    }\n";
5676         pr "    if (strncmp (r, expected, size) != 0) {\n";
5677         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5678         pr "      return -1;\n";
5679         pr "    }\n"
5680       in
5681       List.iter (generate_test_command_call test_name) seq;
5682       generate_test_command_call ~test test_name last
5683   | TestOutputStruct (seq, checks) ->
5684       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5685       let seq, last = get_seq_last seq in
5686       let test () =
5687         List.iter (
5688           function
5689           | CompareWithInt (field, expected) ->
5690               pr "    if (r->%s != %d) {\n" field expected;
5691               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5692                 test_name field expected;
5693               pr "               (int) r->%s);\n" field;
5694               pr "      return -1;\n";
5695               pr "    }\n"
5696           | CompareWithIntOp (field, op, expected) ->
5697               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5698               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5699                 test_name field op expected;
5700               pr "               (int) r->%s);\n" field;
5701               pr "      return -1;\n";
5702               pr "    }\n"
5703           | CompareWithString (field, expected) ->
5704               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5705               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5706                 test_name field expected;
5707               pr "               r->%s);\n" field;
5708               pr "      return -1;\n";
5709               pr "    }\n"
5710           | CompareFieldsIntEq (field1, field2) ->
5711               pr "    if (r->%s != r->%s) {\n" field1 field2;
5712               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5713                 test_name field1 field2;
5714               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5715               pr "      return -1;\n";
5716               pr "    }\n"
5717           | CompareFieldsStrEq (field1, field2) ->
5718               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5719               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5720                 test_name field1 field2;
5721               pr "               r->%s, r->%s);\n" field1 field2;
5722               pr "      return -1;\n";
5723               pr "    }\n"
5724         ) checks
5725       in
5726       List.iter (generate_test_command_call test_name) seq;
5727       generate_test_command_call ~test test_name last
5728   | TestLastFail seq ->
5729       pr "  /* TestLastFail for %s (%d) */\n" name i;
5730       let seq, last = get_seq_last seq in
5731       List.iter (generate_test_command_call test_name) seq;
5732       generate_test_command_call test_name ~expect_error:true last
5733
5734 (* Generate the code to run a command, leaving the result in 'r'.
5735  * If you expect to get an error then you should set expect_error:true.
5736  *)
5737 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5738   match cmd with
5739   | [] -> assert false
5740   | name :: args ->
5741       (* Look up the command to find out what args/ret it has. *)
5742       let style =
5743         try
5744           let _, style, _, _, _, _, _ =
5745             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5746           style
5747         with Not_found ->
5748           failwithf "%s: in test, command %s was not found" test_name name in
5749
5750       if List.length (snd style) <> List.length args then
5751         failwithf "%s: in test, wrong number of args given to %s"
5752           test_name name;
5753
5754       pr "  {\n";
5755
5756       List.iter (
5757         function
5758         | OptString n, "NULL" -> ()
5759         | Pathname n, arg
5760         | Device n, arg
5761         | Dev_or_Path n, arg
5762         | String n, arg
5763         | OptString n, arg ->
5764             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
5765         | Int _, _
5766         | Bool _, _
5767         | FileIn _, _ | FileOut _, _ -> ()
5768         | StringList n, arg ->
5769             let strs = string_split " " arg in
5770             iteri (
5771               fun i str ->
5772                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
5773             ) strs;
5774             pr "    const char *%s[] = {\n" n;
5775             iteri (
5776               fun i _ -> pr "      %s_%d,\n" n i
5777             ) strs;
5778             pr "      NULL\n";
5779             pr "    };\n";
5780       ) (List.combine (snd style) args);
5781
5782       let error_code =
5783         match fst style with
5784         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
5785         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
5786         | RConstString _ | RConstOptString _ ->
5787             pr "    const char *r;\n"; "NULL"
5788         | RString _ -> pr "    char *r;\n"; "NULL"
5789         | RStringList _ | RHashtable _ ->
5790             pr "    char **r;\n";
5791             pr "    int i;\n";
5792             "NULL"
5793         | RStruct (_, typ) ->
5794             pr "    struct guestfs_%s *r;\n" typ; "NULL"
5795         | RStructList (_, typ) ->
5796             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
5797         | RBufferOut _ ->
5798             pr "    char *r;\n";
5799             pr "    size_t size;\n";
5800             "NULL" in
5801
5802       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
5803       pr "    r = guestfs_%s (g" name;
5804
5805       (* Generate the parameters. *)
5806       List.iter (
5807         function
5808         | OptString _, "NULL" -> pr ", NULL"
5809         | Pathname n, _
5810         | Device n, _ | Dev_or_Path n, _
5811         | String n, _
5812         | OptString n, _ ->
5813             pr ", %s" n
5814         | FileIn _, arg | FileOut _, arg ->
5815             pr ", \"%s\"" (c_quote arg)
5816         | StringList n, _ ->
5817             pr ", %s" n
5818         | Int _, arg ->
5819             let i =
5820               try int_of_string arg
5821               with Failure "int_of_string" ->
5822                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
5823             pr ", %d" i
5824         | Bool _, arg ->
5825             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
5826       ) (List.combine (snd style) args);
5827
5828       (match fst style with
5829        | RBufferOut _ -> pr ", &size"
5830        | _ -> ()
5831       );
5832
5833       pr ");\n";
5834
5835       if not expect_error then
5836         pr "    if (r == %s)\n" error_code
5837       else
5838         pr "    if (r != %s)\n" error_code;
5839       pr "      return -1;\n";
5840
5841       (* Insert the test code. *)
5842       (match test with
5843        | None -> ()
5844        | Some f -> f ()
5845       );
5846
5847       (match fst style with
5848        | RErr | RInt _ | RInt64 _ | RBool _
5849        | RConstString _ | RConstOptString _ -> ()
5850        | RString _ | RBufferOut _ -> pr "    free (r);\n"
5851        | RStringList _ | RHashtable _ ->
5852            pr "    for (i = 0; r[i] != NULL; ++i)\n";
5853            pr "      free (r[i]);\n";
5854            pr "    free (r);\n"
5855        | RStruct (_, typ) ->
5856            pr "    guestfs_free_%s (r);\n" typ
5857        | RStructList (_, typ) ->
5858            pr "    guestfs_free_%s_list (r);\n" typ
5859       );
5860
5861       pr "  }\n"
5862
5863 and c_quote str =
5864   let str = replace_str str "\r" "\\r" in
5865   let str = replace_str str "\n" "\\n" in
5866   let str = replace_str str "\t" "\\t" in
5867   let str = replace_str str "\000" "\\0" in
5868   str
5869
5870 (* Generate a lot of different functions for guestfish. *)
5871 and generate_fish_cmds () =
5872   generate_header CStyle GPLv2;
5873
5874   let all_functions =
5875     List.filter (
5876       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5877     ) all_functions in
5878   let all_functions_sorted =
5879     List.filter (
5880       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
5881     ) all_functions_sorted in
5882
5883   pr "#include <stdio.h>\n";
5884   pr "#include <stdlib.h>\n";
5885   pr "#include <string.h>\n";
5886   pr "#include <inttypes.h>\n";
5887   pr "#include <ctype.h>\n";
5888   pr "\n";
5889   pr "#include <guestfs.h>\n";
5890   pr "#include \"fish.h\"\n";
5891   pr "\n";
5892
5893   (* list_commands function, which implements guestfish -h *)
5894   pr "void list_commands (void)\n";
5895   pr "{\n";
5896   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
5897   pr "  list_builtin_commands ();\n";
5898   List.iter (
5899     fun (name, _, _, flags, _, shortdesc, _) ->
5900       let name = replace_char name '_' '-' in
5901       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
5902         name shortdesc
5903   ) all_functions_sorted;
5904   pr "  printf (\"    %%s\\n\",";
5905   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
5906   pr "}\n";
5907   pr "\n";
5908
5909   (* display_command function, which implements guestfish -h cmd *)
5910   pr "void display_command (const char *cmd)\n";
5911   pr "{\n";
5912   List.iter (
5913     fun (name, style, _, flags, _, shortdesc, longdesc) ->
5914       let name2 = replace_char name '_' '-' in
5915       let alias =
5916         try find_map (function FishAlias n -> Some n | _ -> None) flags
5917         with Not_found -> name in
5918       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
5919       let synopsis =
5920         match snd style with
5921         | [] -> name2
5922         | args ->
5923             sprintf "%s <%s>"
5924               name2 (String.concat "> <" (List.map name_of_argt args)) in
5925
5926       let warnings =
5927         if List.mem ProtocolLimitWarning flags then
5928           ("\n\n" ^ protocol_limit_warning)
5929         else "" in
5930
5931       (* For DangerWillRobinson commands, we should probably have
5932        * guestfish prompt before allowing you to use them (especially
5933        * in interactive mode). XXX
5934        *)
5935       let warnings =
5936         warnings ^
5937           if List.mem DangerWillRobinson flags then
5938             ("\n\n" ^ danger_will_robinson)
5939           else "" in
5940
5941       let warnings =
5942         warnings ^
5943           match deprecation_notice flags with
5944           | None -> ""
5945           | Some txt -> "\n\n" ^ txt in
5946
5947       let describe_alias =
5948         if name <> alias then
5949           sprintf "\n\nYou can use '%s' as an alias for this command." alias
5950         else "" in
5951
5952       pr "  if (";
5953       pr "strcasecmp (cmd, \"%s\") == 0" name;
5954       if name <> name2 then
5955         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
5956       if name <> alias then
5957         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
5958       pr ")\n";
5959       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
5960         name2 shortdesc
5961         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
5962       pr "  else\n"
5963   ) all_functions;
5964   pr "    display_builtin_command (cmd);\n";
5965   pr "}\n";
5966   pr "\n";
5967
5968   (* print_* functions *)
5969   List.iter (
5970     fun (typ, cols) ->
5971       let needs_i =
5972         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
5973
5974       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
5975       pr "{\n";
5976       if needs_i then (
5977         pr "  int i;\n";
5978         pr "\n"
5979       );
5980       List.iter (
5981         function
5982         | name, FString ->
5983             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
5984         | name, FUUID ->
5985             pr "  printf (\"%s: \");\n" name;
5986             pr "  for (i = 0; i < 32; ++i)\n";
5987             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5988             pr "  printf (\"\\n\");\n"
5989         | name, FBuffer ->
5990             pr "  printf (\"%%s%s: \", indent);\n" name;
5991             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
5992             pr "    if (isprint (%s->%s[i]))\n" typ name;
5993             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
5994             pr "    else\n";
5995             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
5996             pr "  printf (\"\\n\");\n"
5997         | name, (FUInt64|FBytes) ->
5998             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
5999               name typ name
6000         | name, FInt64 ->
6001             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6002               name typ name
6003         | name, FUInt32 ->
6004             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6005               name typ name
6006         | name, FInt32 ->
6007             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6008               name typ name
6009         | name, FChar ->
6010             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6011               name typ name
6012         | name, FOptPercent ->
6013             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6014               typ name name typ name;
6015             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6016       ) cols;
6017       pr "}\n";
6018       pr "\n";
6019       pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6020       pr "{\n";
6021       pr "  print_%s_indent (%s, \"\");\n" typ typ;
6022       pr "}\n";
6023       pr "\n";
6024       pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6025         typ typ typ;
6026       pr "{\n";
6027       pr "  int i;\n";
6028       pr "\n";
6029       pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6030       pr "    printf (\"[%%d] = {\\n\", i);\n";
6031       pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6032       pr "    printf (\"}\\n\");\n";
6033       pr "  }\n";
6034       pr "}\n";
6035       pr "\n";
6036   ) structs;
6037
6038   (* run_<action> actions *)
6039   List.iter (
6040     fun (name, style, _, flags, _, _, _) ->
6041       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6042       pr "{\n";
6043       (match fst style with
6044        | RErr
6045        | RInt _
6046        | RBool _ -> pr "  int r;\n"
6047        | RInt64 _ -> pr "  int64_t r;\n"
6048        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6049        | RString _ -> pr "  char *r;\n"
6050        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6051        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6052        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6053        | RBufferOut _ ->
6054            pr "  char *r;\n";
6055            pr "  size_t size;\n";
6056       );
6057       List.iter (
6058         function
6059         | Pathname n
6060         | Device n | Dev_or_Path n
6061         | String n
6062         | OptString n
6063         | FileIn n
6064         | FileOut n -> pr "  const char *%s;\n" n
6065         | StringList n -> pr "  char **%s;\n" n
6066         | Bool n -> pr "  int %s;\n" n
6067         | Int n -> pr "  int %s;\n" n
6068       ) (snd style);
6069
6070       (* Check and convert parameters. *)
6071       let argc_expected = List.length (snd style) in
6072       pr "  if (argc != %d) {\n" argc_expected;
6073       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6074         argc_expected;
6075       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6076       pr "    return -1;\n";
6077       pr "  }\n";
6078       iteri (
6079         fun i ->
6080           function
6081           | Pathname name
6082           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6083           | OptString name ->
6084               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6085                 name i i
6086           | FileIn name ->
6087               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6088                 name i i
6089           | FileOut name ->
6090               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6091                 name i i
6092           | StringList name ->
6093               pr "  %s = parse_string_list (argv[%d]);\n" name i
6094           | Bool name ->
6095               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6096           | Int name ->
6097               pr "  %s = atoi (argv[%d]);\n" name i
6098       ) (snd style);
6099
6100       (* Call C API function. *)
6101       let fn =
6102         try find_map (function FishAction n -> Some n | _ -> None) flags
6103         with Not_found -> sprintf "guestfs_%s" name in
6104       pr "  r = %s " fn;
6105       generate_c_call_args ~handle:"g" style;
6106       pr ";\n";
6107
6108       (* Check return value for errors and display command results. *)
6109       (match fst style with
6110        | RErr -> pr "  return r;\n"
6111        | RInt _ ->
6112            pr "  if (r == -1) return -1;\n";
6113            pr "  printf (\"%%d\\n\", r);\n";
6114            pr "  return 0;\n"
6115        | RInt64 _ ->
6116            pr "  if (r == -1) return -1;\n";
6117            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6118            pr "  return 0;\n"
6119        | RBool _ ->
6120            pr "  if (r == -1) return -1;\n";
6121            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6122            pr "  return 0;\n"
6123        | RConstString _ ->
6124            pr "  if (r == NULL) return -1;\n";
6125            pr "  printf (\"%%s\\n\", r);\n";
6126            pr "  return 0;\n"
6127        | RConstOptString _ ->
6128            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6129            pr "  return 0;\n"
6130        | RString _ ->
6131            pr "  if (r == NULL) return -1;\n";
6132            pr "  printf (\"%%s\\n\", r);\n";
6133            pr "  free (r);\n";
6134            pr "  return 0;\n"
6135        | RStringList _ ->
6136            pr "  if (r == NULL) return -1;\n";
6137            pr "  print_strings (r);\n";
6138            pr "  free_strings (r);\n";
6139            pr "  return 0;\n"
6140        | RStruct (_, typ) ->
6141            pr "  if (r == NULL) return -1;\n";
6142            pr "  print_%s (r);\n" typ;
6143            pr "  guestfs_free_%s (r);\n" typ;
6144            pr "  return 0;\n"
6145        | RStructList (_, typ) ->
6146            pr "  if (r == NULL) return -1;\n";
6147            pr "  print_%s_list (r);\n" typ;
6148            pr "  guestfs_free_%s_list (r);\n" typ;
6149            pr "  return 0;\n"
6150        | RHashtable _ ->
6151            pr "  if (r == NULL) return -1;\n";
6152            pr "  print_table (r);\n";
6153            pr "  free_strings (r);\n";
6154            pr "  return 0;\n"
6155        | RBufferOut _ ->
6156            pr "  if (r == NULL) return -1;\n";
6157            pr "  fwrite (r, size, 1, stdout);\n";
6158            pr "  free (r);\n";
6159            pr "  return 0;\n"
6160       );
6161       pr "}\n";
6162       pr "\n"
6163   ) all_functions;
6164
6165   (* run_action function *)
6166   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6167   pr "{\n";
6168   List.iter (
6169     fun (name, _, _, flags, _, _, _) ->
6170       let name2 = replace_char name '_' '-' in
6171       let alias =
6172         try find_map (function FishAlias n -> Some n | _ -> None) flags
6173         with Not_found -> name in
6174       pr "  if (";
6175       pr "strcasecmp (cmd, \"%s\") == 0" name;
6176       if name <> name2 then
6177         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6178       if name <> alias then
6179         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6180       pr ")\n";
6181       pr "    return run_%s (cmd, argc, argv);\n" name;
6182       pr "  else\n";
6183   ) all_functions;
6184   pr "    {\n";
6185   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6186   pr "      return -1;\n";
6187   pr "    }\n";
6188   pr "  return 0;\n";
6189   pr "}\n";
6190   pr "\n"
6191
6192 (* Readline completion for guestfish. *)
6193 and generate_fish_completion () =
6194   generate_header CStyle GPLv2;
6195
6196   let all_functions =
6197     List.filter (
6198       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6199     ) all_functions in
6200
6201   pr "\
6202 #include <config.h>
6203
6204 #include <stdio.h>
6205 #include <stdlib.h>
6206 #include <string.h>
6207
6208 #ifdef HAVE_LIBREADLINE
6209 #include <readline/readline.h>
6210 #endif
6211
6212 #include \"fish.h\"
6213
6214 #ifdef HAVE_LIBREADLINE
6215
6216 static const char *const commands[] = {
6217   BUILTIN_COMMANDS_FOR_COMPLETION,
6218 ";
6219
6220   (* Get the commands, including the aliases.  They don't need to be
6221    * sorted - the generator() function just does a dumb linear search.
6222    *)
6223   let commands =
6224     List.map (
6225       fun (name, _, _, flags, _, _, _) ->
6226         let name2 = replace_char name '_' '-' in
6227         let alias =
6228           try find_map (function FishAlias n -> Some n | _ -> None) flags
6229           with Not_found -> name in
6230
6231         if name <> alias then [name2; alias] else [name2]
6232     ) all_functions in
6233   let commands = List.flatten commands in
6234
6235   List.iter (pr "  \"%s\",\n") commands;
6236
6237   pr "  NULL
6238 };
6239
6240 static char *
6241 generator (const char *text, int state)
6242 {
6243   static int index, len;
6244   const char *name;
6245
6246   if (!state) {
6247     index = 0;
6248     len = strlen (text);
6249   }
6250
6251   rl_attempted_completion_over = 1;
6252
6253   while ((name = commands[index]) != NULL) {
6254     index++;
6255     if (strncasecmp (name, text, len) == 0)
6256       return strdup (name);
6257   }
6258
6259   return NULL;
6260 }
6261
6262 #endif /* HAVE_LIBREADLINE */
6263
6264 char **do_completion (const char *text, int start, int end)
6265 {
6266   char **matches = NULL;
6267
6268 #ifdef HAVE_LIBREADLINE
6269   rl_completion_append_character = ' ';
6270
6271   if (start == 0)
6272     matches = rl_completion_matches (text, generator);
6273   else if (complete_dest_paths)
6274     matches = rl_completion_matches (text, complete_dest_paths_generator);
6275 #endif
6276
6277   return matches;
6278 }
6279 ";
6280
6281 (* Generate the POD documentation for guestfish. *)
6282 and generate_fish_actions_pod () =
6283   let all_functions_sorted =
6284     List.filter (
6285       fun (_, _, _, flags, _, _, _) ->
6286         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6287     ) all_functions_sorted in
6288
6289   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6290
6291   List.iter (
6292     fun (name, style, _, flags, _, _, longdesc) ->
6293       let longdesc =
6294         Str.global_substitute rex (
6295           fun s ->
6296             let sub =
6297               try Str.matched_group 1 s
6298               with Not_found ->
6299                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6300             "C<" ^ replace_char sub '_' '-' ^ ">"
6301         ) longdesc in
6302       let name = replace_char name '_' '-' in
6303       let alias =
6304         try find_map (function FishAlias n -> Some n | _ -> None) flags
6305         with Not_found -> name in
6306
6307       pr "=head2 %s" name;
6308       if name <> alias then
6309         pr " | %s" alias;
6310       pr "\n";
6311       pr "\n";
6312       pr " %s" name;
6313       List.iter (
6314         function
6315         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6316         | OptString n -> pr " %s" n
6317         | StringList n -> pr " '%s ...'" n
6318         | Bool _ -> pr " true|false"
6319         | Int n -> pr " %s" n
6320         | FileIn n | FileOut n -> pr " (%s|-)" n
6321       ) (snd style);
6322       pr "\n";
6323       pr "\n";
6324       pr "%s\n\n" longdesc;
6325
6326       if List.exists (function FileIn _ | FileOut _ -> true
6327                       | _ -> false) (snd style) then
6328         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6329
6330       if List.mem ProtocolLimitWarning flags then
6331         pr "%s\n\n" protocol_limit_warning;
6332
6333       if List.mem DangerWillRobinson flags then
6334         pr "%s\n\n" danger_will_robinson;
6335
6336       match deprecation_notice flags with
6337       | None -> ()
6338       | Some txt -> pr "%s\n\n" txt
6339   ) all_functions_sorted
6340
6341 (* Generate a C function prototype. *)
6342 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6343     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6344     ?(prefix = "")
6345     ?handle name style =
6346   if extern then pr "extern ";
6347   if static then pr "static ";
6348   (match fst style with
6349    | RErr -> pr "int "
6350    | RInt _ -> pr "int "
6351    | RInt64 _ -> pr "int64_t "
6352    | RBool _ -> pr "int "
6353    | RConstString _ | RConstOptString _ -> pr "const char *"
6354    | RString _ | RBufferOut _ -> pr "char *"
6355    | RStringList _ | RHashtable _ -> pr "char **"
6356    | RStruct (_, typ) ->
6357        if not in_daemon then pr "struct guestfs_%s *" typ
6358        else pr "guestfs_int_%s *" typ
6359    | RStructList (_, typ) ->
6360        if not in_daemon then pr "struct guestfs_%s_list *" typ
6361        else pr "guestfs_int_%s_list *" typ
6362   );
6363   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6364   pr "%s%s (" prefix name;
6365   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6366     pr "void"
6367   else (
6368     let comma = ref false in
6369     (match handle with
6370      | None -> ()
6371      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6372     );
6373     let next () =
6374       if !comma then (
6375         if single_line then pr ", " else pr ",\n\t\t"
6376       );
6377       comma := true
6378     in
6379     List.iter (
6380       function
6381       | Pathname n
6382       | Device n | Dev_or_Path n
6383       | String n
6384       | OptString n ->
6385           next ();
6386           pr "const char *%s" n
6387       | StringList n ->
6388           next ();
6389           if not in_daemon then pr "char * const* const %s" n
6390           else pr "char **%s" n
6391       | Bool n -> next (); pr "int %s" n
6392       | Int n -> next (); pr "int %s" n
6393       | FileIn n
6394       | FileOut n ->
6395           if not in_daemon then (next (); pr "const char *%s" n)
6396     ) (snd style);
6397     if is_RBufferOut then (next (); pr "size_t *size_r");
6398   );
6399   pr ")";
6400   if semicolon then pr ";";
6401   if newline then pr "\n"
6402
6403 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6404 and generate_c_call_args ?handle ?(decl = false) style =
6405   pr "(";
6406   let comma = ref false in
6407   let next () =
6408     if !comma then pr ", ";
6409     comma := true
6410   in
6411   (match handle with
6412    | None -> ()
6413    | Some handle -> pr "%s" handle; comma := true
6414   );
6415   List.iter (
6416     fun arg ->
6417       next ();
6418       pr "%s" (name_of_argt arg)
6419   ) (snd style);
6420   (* For RBufferOut calls, add implicit &size parameter. *)
6421   if not decl then (
6422     match fst style with
6423     | RBufferOut _ ->
6424         next ();
6425         pr "&size"
6426     | _ -> ()
6427   );
6428   pr ")"
6429
6430 (* Generate the OCaml bindings interface. *)
6431 and generate_ocaml_mli () =
6432   generate_header OCamlStyle LGPLv2;
6433
6434   pr "\
6435 (** For API documentation you should refer to the C API
6436     in the guestfs(3) manual page.  The OCaml API uses almost
6437     exactly the same calls. *)
6438
6439 type t
6440 (** A [guestfs_h] handle. *)
6441
6442 exception Error of string
6443 (** This exception is raised when there is an error. *)
6444
6445 val create : unit -> t
6446
6447 val close : t -> unit
6448 (** Handles are closed by the garbage collector when they become
6449     unreferenced, but callers can also call this in order to
6450     provide predictable cleanup. *)
6451
6452 ";
6453   generate_ocaml_structure_decls ();
6454
6455   (* The actions. *)
6456   List.iter (
6457     fun (name, style, _, _, _, shortdesc, _) ->
6458       generate_ocaml_prototype name style;
6459       pr "(** %s *)\n" shortdesc;
6460       pr "\n"
6461   ) all_functions
6462
6463 (* Generate the OCaml bindings implementation. *)
6464 and generate_ocaml_ml () =
6465   generate_header OCamlStyle LGPLv2;
6466
6467   pr "\
6468 type t
6469 exception Error of string
6470 external create : unit -> t = \"ocaml_guestfs_create\"
6471 external close : t -> unit = \"ocaml_guestfs_close\"
6472
6473 let () =
6474   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6475
6476 ";
6477
6478   generate_ocaml_structure_decls ();
6479
6480   (* The actions. *)
6481   List.iter (
6482     fun (name, style, _, _, _, shortdesc, _) ->
6483       generate_ocaml_prototype ~is_external:true name style;
6484   ) all_functions
6485
6486 (* Generate the OCaml bindings C implementation. *)
6487 and generate_ocaml_c () =
6488   generate_header CStyle LGPLv2;
6489
6490   pr "\
6491 #include <stdio.h>
6492 #include <stdlib.h>
6493 #include <string.h>
6494
6495 #include <caml/config.h>
6496 #include <caml/alloc.h>
6497 #include <caml/callback.h>
6498 #include <caml/fail.h>
6499 #include <caml/memory.h>
6500 #include <caml/mlvalues.h>
6501 #include <caml/signals.h>
6502
6503 #include <guestfs.h>
6504
6505 #include \"guestfs_c.h\"
6506
6507 /* Copy a hashtable of string pairs into an assoc-list.  We return
6508  * the list in reverse order, but hashtables aren't supposed to be
6509  * ordered anyway.
6510  */
6511 static CAMLprim value
6512 copy_table (char * const * argv)
6513 {
6514   CAMLparam0 ();
6515   CAMLlocal5 (rv, pairv, kv, vv, cons);
6516   int i;
6517
6518   rv = Val_int (0);
6519   for (i = 0; argv[i] != NULL; i += 2) {
6520     kv = caml_copy_string (argv[i]);
6521     vv = caml_copy_string (argv[i+1]);
6522     pairv = caml_alloc (2, 0);
6523     Store_field (pairv, 0, kv);
6524     Store_field (pairv, 1, vv);
6525     cons = caml_alloc (2, 0);
6526     Store_field (cons, 1, rv);
6527     rv = cons;
6528     Store_field (cons, 0, pairv);
6529   }
6530
6531   CAMLreturn (rv);
6532 }
6533
6534 ";
6535
6536   (* Struct copy functions. *)
6537   List.iter (
6538     fun (typ, cols) ->
6539       let has_optpercent_col =
6540         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6541
6542       pr "static CAMLprim value\n";
6543       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6544       pr "{\n";
6545       pr "  CAMLparam0 ();\n";
6546       if has_optpercent_col then
6547         pr "  CAMLlocal3 (rv, v, v2);\n"
6548       else
6549         pr "  CAMLlocal2 (rv, v);\n";
6550       pr "\n";
6551       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6552       iteri (
6553         fun i col ->
6554           (match col with
6555            | name, FString ->
6556                pr "  v = caml_copy_string (%s->%s);\n" typ name
6557            | name, FBuffer ->
6558                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6559                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6560                  typ name typ name
6561            | name, FUUID ->
6562                pr "  v = caml_alloc_string (32);\n";
6563                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6564            | name, (FBytes|FInt64|FUInt64) ->
6565                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6566            | name, (FInt32|FUInt32) ->
6567                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6568            | name, FOptPercent ->
6569                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6570                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6571                pr "    v = caml_alloc (1, 0);\n";
6572                pr "    Store_field (v, 0, v2);\n";
6573                pr "  } else /* None */\n";
6574                pr "    v = Val_int (0);\n";
6575            | name, FChar ->
6576                pr "  v = Val_int (%s->%s);\n" typ name
6577           );
6578           pr "  Store_field (rv, %d, v);\n" i
6579       ) cols;
6580       pr "  CAMLreturn (rv);\n";
6581       pr "}\n";
6582       pr "\n";
6583
6584       pr "static CAMLprim value\n";
6585       pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n"
6586         typ typ typ;
6587       pr "{\n";
6588       pr "  CAMLparam0 ();\n";
6589       pr "  CAMLlocal2 (rv, v);\n";
6590       pr "  int i;\n";
6591       pr "\n";
6592       pr "  if (%ss->len == 0)\n" typ;
6593       pr "    CAMLreturn (Atom (0));\n";
6594       pr "  else {\n";
6595       pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6596       pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6597       pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6598       pr "      caml_modify (&Field (rv, i), v);\n";
6599       pr "    }\n";
6600       pr "    CAMLreturn (rv);\n";
6601       pr "  }\n";
6602       pr "}\n";
6603       pr "\n";
6604   ) structs;
6605
6606   (* The wrappers. *)
6607   List.iter (
6608     fun (name, style, _, _, _, _, _) ->
6609       let params =
6610         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6611
6612       let needs_extra_vs =
6613         match fst style with RConstOptString _ -> true | _ -> false in
6614
6615       pr "CAMLprim value\n";
6616       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6617       List.iter (pr ", value %s") (List.tl params);
6618       pr ")\n";
6619       pr "{\n";
6620
6621       (match params with
6622        | [p1; p2; p3; p4; p5] ->
6623            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6624        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6625            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6626            pr "  CAMLxparam%d (%s);\n"
6627              (List.length rest) (String.concat ", " rest)
6628        | ps ->
6629            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6630       );
6631       if not needs_extra_vs then
6632         pr "  CAMLlocal1 (rv);\n"
6633       else
6634         pr "  CAMLlocal3 (rv, v, v2);\n";
6635       pr "\n";
6636
6637       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6638       pr "  if (g == NULL)\n";
6639       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6640       pr "\n";
6641
6642       List.iter (
6643         function
6644         | Pathname n
6645         | Device n | Dev_or_Path n
6646         | String n
6647         | FileIn n
6648         | FileOut n ->
6649             pr "  const char *%s = String_val (%sv);\n" n n
6650         | OptString n ->
6651             pr "  const char *%s =\n" n;
6652             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6653               n n
6654         | StringList n ->
6655             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6656         | Bool n ->
6657             pr "  int %s = Bool_val (%sv);\n" n n
6658         | Int n ->
6659             pr "  int %s = Int_val (%sv);\n" n n
6660       ) (snd style);
6661       let error_code =
6662         match fst style with
6663         | RErr -> pr "  int r;\n"; "-1"
6664         | RInt _ -> pr "  int r;\n"; "-1"
6665         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6666         | RBool _ -> pr "  int r;\n"; "-1"
6667         | RConstString _ | RConstOptString _ ->
6668             pr "  const char *r;\n"; "NULL"
6669         | RString _ -> pr "  char *r;\n"; "NULL"
6670         | RStringList _ ->
6671             pr "  int i;\n";
6672             pr "  char **r;\n";
6673             "NULL"
6674         | RStruct (_, typ) ->
6675             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6676         | RStructList (_, typ) ->
6677             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6678         | RHashtable _ ->
6679             pr "  int i;\n";
6680             pr "  char **r;\n";
6681             "NULL"
6682         | RBufferOut _ ->
6683             pr "  char *r;\n";
6684             pr "  size_t size;\n";
6685             "NULL" in
6686       pr "\n";
6687
6688       pr "  caml_enter_blocking_section ();\n";
6689       pr "  r = guestfs_%s " name;
6690       generate_c_call_args ~handle:"g" style;
6691       pr ";\n";
6692       pr "  caml_leave_blocking_section ();\n";
6693
6694       List.iter (
6695         function
6696         | StringList n ->
6697             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6698         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6699         | FileIn _ | FileOut _ -> ()
6700       ) (snd style);
6701
6702       pr "  if (r == %s)\n" error_code;
6703       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6704       pr "\n";
6705
6706       (match fst style with
6707        | RErr -> pr "  rv = Val_unit;\n"
6708        | RInt _ -> pr "  rv = Val_int (r);\n"
6709        | RInt64 _ ->
6710            pr "  rv = caml_copy_int64 (r);\n"
6711        | RBool _ -> pr "  rv = Val_bool (r);\n"
6712        | RConstString _ ->
6713            pr "  rv = caml_copy_string (r);\n"
6714        | RConstOptString _ ->
6715            pr "  if (r) { /* Some string */\n";
6716            pr "    v = caml_alloc (1, 0);\n";
6717            pr "    v2 = caml_copy_string (r);\n";
6718            pr "    Store_field (v, 0, v2);\n";
6719            pr "  } else /* None */\n";
6720            pr "    v = Val_int (0);\n";
6721        | RString _ ->
6722            pr "  rv = caml_copy_string (r);\n";
6723            pr "  free (r);\n"
6724        | RStringList _ ->
6725            pr "  rv = caml_copy_string_array ((const char **) r);\n";
6726            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6727            pr "  free (r);\n"
6728        | RStruct (_, typ) ->
6729            pr "  rv = copy_%s (r);\n" typ;
6730            pr "  guestfs_free_%s (r);\n" typ;
6731        | RStructList (_, typ) ->
6732            pr "  rv = copy_%s_list (r);\n" typ;
6733            pr "  guestfs_free_%s_list (r);\n" typ;
6734        | RHashtable _ ->
6735            pr "  rv = copy_table (r);\n";
6736            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6737            pr "  free (r);\n";
6738        | RBufferOut _ ->
6739            pr "  rv = caml_alloc_string (size);\n";
6740            pr "  memcpy (String_val (rv), r, size);\n";
6741       );
6742
6743       pr "  CAMLreturn (rv);\n";
6744       pr "}\n";
6745       pr "\n";
6746
6747       if List.length params > 5 then (
6748         pr "CAMLprim value\n";
6749         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
6750         pr "{\n";
6751         pr "  return ocaml_guestfs_%s (argv[0]" name;
6752         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
6753         pr ");\n";
6754         pr "}\n";
6755         pr "\n"
6756       )
6757   ) all_functions
6758
6759 and generate_ocaml_structure_decls () =
6760   List.iter (
6761     fun (typ, cols) ->
6762       pr "type %s = {\n" typ;
6763       List.iter (
6764         function
6765         | name, FString -> pr "  %s : string;\n" name
6766         | name, FBuffer -> pr "  %s : string;\n" name
6767         | name, FUUID -> pr "  %s : string;\n" name
6768         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
6769         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
6770         | name, FChar -> pr "  %s : char;\n" name
6771         | name, FOptPercent -> pr "  %s : float option;\n" name
6772       ) cols;
6773       pr "}\n";
6774       pr "\n"
6775   ) structs
6776
6777 and generate_ocaml_prototype ?(is_external = false) name style =
6778   if is_external then pr "external " else pr "val ";
6779   pr "%s : t -> " name;
6780   List.iter (
6781     function
6782     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
6783     | OptString _ -> pr "string option -> "
6784     | StringList _ -> pr "string array -> "
6785     | Bool _ -> pr "bool -> "
6786     | Int _ -> pr "int -> "
6787   ) (snd style);
6788   (match fst style with
6789    | RErr -> pr "unit" (* all errors are turned into exceptions *)
6790    | RInt _ -> pr "int"
6791    | RInt64 _ -> pr "int64"
6792    | RBool _ -> pr "bool"
6793    | RConstString _ -> pr "string"
6794    | RConstOptString _ -> pr "string option"
6795    | RString _ | RBufferOut _ -> pr "string"
6796    | RStringList _ -> pr "string array"
6797    | RStruct (_, typ) -> pr "%s" typ
6798    | RStructList (_, typ) -> pr "%s array" typ
6799    | RHashtable _ -> pr "(string * string) list"
6800   );
6801   if is_external then (
6802     pr " = ";
6803     if List.length (snd style) + 1 > 5 then
6804       pr "\"ocaml_guestfs_%s_byte\" " name;
6805     pr "\"ocaml_guestfs_%s\"" name
6806   );
6807   pr "\n"
6808
6809 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
6810 and generate_perl_xs () =
6811   generate_header CStyle LGPLv2;
6812
6813   pr "\
6814 #include \"EXTERN.h\"
6815 #include \"perl.h\"
6816 #include \"XSUB.h\"
6817
6818 #include <guestfs.h>
6819
6820 #ifndef PRId64
6821 #define PRId64 \"lld\"
6822 #endif
6823
6824 static SV *
6825 my_newSVll(long long val) {
6826 #ifdef USE_64_BIT_ALL
6827   return newSViv(val);
6828 #else
6829   char buf[100];
6830   int len;
6831   len = snprintf(buf, 100, \"%%\" PRId64, val);
6832   return newSVpv(buf, len);
6833 #endif
6834 }
6835
6836 #ifndef PRIu64
6837 #define PRIu64 \"llu\"
6838 #endif
6839
6840 static SV *
6841 my_newSVull(unsigned long long val) {
6842 #ifdef USE_64_BIT_ALL
6843   return newSVuv(val);
6844 #else
6845   char buf[100];
6846   int len;
6847   len = snprintf(buf, 100, \"%%\" PRIu64, val);
6848   return newSVpv(buf, len);
6849 #endif
6850 }
6851
6852 /* http://www.perlmonks.org/?node_id=680842 */
6853 static char **
6854 XS_unpack_charPtrPtr (SV *arg) {
6855   char **ret;
6856   AV *av;
6857   I32 i;
6858
6859   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
6860     croak (\"array reference expected\");
6861
6862   av = (AV *)SvRV (arg);
6863   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
6864   if (!ret)
6865     croak (\"malloc failed\");
6866
6867   for (i = 0; i <= av_len (av); i++) {
6868     SV **elem = av_fetch (av, i, 0);
6869
6870     if (!elem || !*elem)
6871       croak (\"missing element in list\");
6872
6873     ret[i] = SvPV_nolen (*elem);
6874   }
6875
6876   ret[i] = NULL;
6877
6878   return ret;
6879 }
6880
6881 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
6882
6883 PROTOTYPES: ENABLE
6884
6885 guestfs_h *
6886 _create ()
6887    CODE:
6888       RETVAL = guestfs_create ();
6889       if (!RETVAL)
6890         croak (\"could not create guestfs handle\");
6891       guestfs_set_error_handler (RETVAL, NULL, NULL);
6892  OUTPUT:
6893       RETVAL
6894
6895 void
6896 DESTROY (g)
6897       guestfs_h *g;
6898  PPCODE:
6899       guestfs_close (g);
6900
6901 ";
6902
6903   List.iter (
6904     fun (name, style, _, _, _, _, _) ->
6905       (match fst style with
6906        | RErr -> pr "void\n"
6907        | RInt _ -> pr "SV *\n"
6908        | RInt64 _ -> pr "SV *\n"
6909        | RBool _ -> pr "SV *\n"
6910        | RConstString _ -> pr "SV *\n"
6911        | RConstOptString _ -> pr "SV *\n"
6912        | RString _ -> pr "SV *\n"
6913        | RBufferOut _ -> pr "SV *\n"
6914        | RStringList _
6915        | RStruct _ | RStructList _
6916        | RHashtable _ ->
6917            pr "void\n" (* all lists returned implictly on the stack *)
6918       );
6919       (* Call and arguments. *)
6920       pr "%s " name;
6921       generate_c_call_args ~handle:"g" ~decl:true style;
6922       pr "\n";
6923       pr "      guestfs_h *g;\n";
6924       iteri (
6925         fun i ->
6926           function
6927           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
6928               pr "      char *%s;\n" n
6929           | OptString n ->
6930               (* http://www.perlmonks.org/?node_id=554277
6931                * Note that the implicit handle argument means we have
6932                * to add 1 to the ST(x) operator.
6933                *)
6934               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
6935           | StringList n -> pr "      char **%s;\n" n
6936           | Bool n -> pr "      int %s;\n" n
6937           | Int n -> pr "      int %s;\n" n
6938       ) (snd style);
6939
6940       let do_cleanups () =
6941         List.iter (
6942           function
6943           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6944           | FileIn _ | FileOut _ -> ()
6945           | StringList n -> pr "      free (%s);\n" n
6946         ) (snd style)
6947       in
6948
6949       (* Code. *)
6950       (match fst style with
6951        | RErr ->
6952            pr "PREINIT:\n";
6953            pr "      int r;\n";
6954            pr " PPCODE:\n";
6955            pr "      r = guestfs_%s " name;
6956            generate_c_call_args ~handle:"g" style;
6957            pr ";\n";
6958            do_cleanups ();
6959            pr "      if (r == -1)\n";
6960            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6961        | RInt n
6962        | RBool n ->
6963            pr "PREINIT:\n";
6964            pr "      int %s;\n" n;
6965            pr "   CODE:\n";
6966            pr "      %s = guestfs_%s " n name;
6967            generate_c_call_args ~handle:"g" style;
6968            pr ";\n";
6969            do_cleanups ();
6970            pr "      if (%s == -1)\n" n;
6971            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6972            pr "      RETVAL = newSViv (%s);\n" n;
6973            pr " OUTPUT:\n";
6974            pr "      RETVAL\n"
6975        | RInt64 n ->
6976            pr "PREINIT:\n";
6977            pr "      int64_t %s;\n" n;
6978            pr "   CODE:\n";
6979            pr "      %s = guestfs_%s " n name;
6980            generate_c_call_args ~handle:"g" style;
6981            pr ";\n";
6982            do_cleanups ();
6983            pr "      if (%s == -1)\n" n;
6984            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6985            pr "      RETVAL = my_newSVll (%s);\n" n;
6986            pr " OUTPUT:\n";
6987            pr "      RETVAL\n"
6988        | RConstString n ->
6989            pr "PREINIT:\n";
6990            pr "      const char *%s;\n" n;
6991            pr "   CODE:\n";
6992            pr "      %s = guestfs_%s " n name;
6993            generate_c_call_args ~handle:"g" style;
6994            pr ";\n";
6995            do_cleanups ();
6996            pr "      if (%s == NULL)\n" n;
6997            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
6998            pr "      RETVAL = newSVpv (%s, 0);\n" n;
6999            pr " OUTPUT:\n";
7000            pr "      RETVAL\n"
7001        | RConstOptString n ->
7002            pr "PREINIT:\n";
7003            pr "      const char *%s;\n" n;
7004            pr "   CODE:\n";
7005            pr "      %s = guestfs_%s " n name;
7006            generate_c_call_args ~handle:"g" style;
7007            pr ";\n";
7008            do_cleanups ();
7009            pr "      if (%s == NULL)\n" n;
7010            pr "        RETVAL = &PL_sv_undef;\n";
7011            pr "      else\n";
7012            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7013            pr " OUTPUT:\n";
7014            pr "      RETVAL\n"
7015        | RString n ->
7016            pr "PREINIT:\n";
7017            pr "      char *%s;\n" n;
7018            pr "   CODE:\n";
7019            pr "      %s = guestfs_%s " n name;
7020            generate_c_call_args ~handle:"g" style;
7021            pr ";\n";
7022            do_cleanups ();
7023            pr "      if (%s == NULL)\n" n;
7024            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7025            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7026            pr "      free (%s);\n" n;
7027            pr " OUTPUT:\n";
7028            pr "      RETVAL\n"
7029        | RStringList n | RHashtable n ->
7030            pr "PREINIT:\n";
7031            pr "      char **%s;\n" n;
7032            pr "      int i, n;\n";
7033            pr " PPCODE:\n";
7034            pr "      %s = guestfs_%s " n name;
7035            generate_c_call_args ~handle:"g" style;
7036            pr ";\n";
7037            do_cleanups ();
7038            pr "      if (%s == NULL)\n" n;
7039            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7040            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7041            pr "      EXTEND (SP, n);\n";
7042            pr "      for (i = 0; i < n; ++i) {\n";
7043            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7044            pr "        free (%s[i]);\n" n;
7045            pr "      }\n";
7046            pr "      free (%s);\n" n;
7047        | RStruct (n, typ) ->
7048            let cols = cols_of_struct typ in
7049            generate_perl_struct_code typ cols name style n do_cleanups
7050        | RStructList (n, typ) ->
7051            let cols = cols_of_struct typ in
7052            generate_perl_struct_list_code typ cols name style n do_cleanups
7053        | RBufferOut n ->
7054            pr "PREINIT:\n";
7055            pr "      char *%s;\n" n;
7056            pr "      size_t size;\n";
7057            pr "   CODE:\n";
7058            pr "      %s = guestfs_%s " n name;
7059            generate_c_call_args ~handle:"g" style;
7060            pr ";\n";
7061            do_cleanups ();
7062            pr "      if (%s == NULL)\n" n;
7063            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7064            pr "      RETVAL = newSVpv (%s, size);\n" n;
7065            pr "      free (%s);\n" n;
7066            pr " OUTPUT:\n";
7067            pr "      RETVAL\n"
7068       );
7069
7070       pr "\n"
7071   ) all_functions
7072
7073 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7074   pr "PREINIT:\n";
7075   pr "      struct guestfs_%s_list *%s;\n" typ n;
7076   pr "      int i;\n";
7077   pr "      HV *hv;\n";
7078   pr " PPCODE:\n";
7079   pr "      %s = guestfs_%s " n name;
7080   generate_c_call_args ~handle:"g" style;
7081   pr ";\n";
7082   do_cleanups ();
7083   pr "      if (%s == NULL)\n" n;
7084   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7085   pr "      EXTEND (SP, %s->len);\n" n;
7086   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7087   pr "        hv = newHV ();\n";
7088   List.iter (
7089     function
7090     | name, FString ->
7091         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7092           name (String.length name) n name
7093     | name, FUUID ->
7094         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7095           name (String.length name) n name
7096     | name, FBuffer ->
7097         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7098           name (String.length name) n name n name
7099     | name, (FBytes|FUInt64) ->
7100         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7101           name (String.length name) n name
7102     | name, FInt64 ->
7103         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7104           name (String.length name) n name
7105     | name, (FInt32|FUInt32) ->
7106         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7107           name (String.length name) n name
7108     | name, FChar ->
7109         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7110           name (String.length name) n name
7111     | name, FOptPercent ->
7112         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7113           name (String.length name) n name
7114   ) cols;
7115   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7116   pr "      }\n";
7117   pr "      guestfs_free_%s_list (%s);\n" typ n
7118
7119 and generate_perl_struct_code typ cols name style n do_cleanups =
7120   pr "PREINIT:\n";
7121   pr "      struct guestfs_%s *%s;\n" typ n;
7122   pr " PPCODE:\n";
7123   pr "      %s = guestfs_%s " n name;
7124   generate_c_call_args ~handle:"g" style;
7125   pr ";\n";
7126   do_cleanups ();
7127   pr "      if (%s == NULL)\n" n;
7128   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7129   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7130   List.iter (
7131     fun ((name, _) as col) ->
7132       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7133
7134       match col with
7135       | name, FString ->
7136           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7137             n name
7138       | name, FBuffer ->
7139           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7140             n name n name
7141       | name, FUUID ->
7142           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7143             n name
7144       | name, (FBytes|FUInt64) ->
7145           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7146             n name
7147       | name, FInt64 ->
7148           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7149             n name
7150       | name, (FInt32|FUInt32) ->
7151           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7152             n name
7153       | name, FChar ->
7154           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7155             n name
7156       | name, FOptPercent ->
7157           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7158             n name
7159   ) cols;
7160   pr "      free (%s);\n" n
7161
7162 (* Generate Sys/Guestfs.pm. *)
7163 and generate_perl_pm () =
7164   generate_header HashStyle LGPLv2;
7165
7166   pr "\
7167 =pod
7168
7169 =head1 NAME
7170
7171 Sys::Guestfs - Perl bindings for libguestfs
7172
7173 =head1 SYNOPSIS
7174
7175  use Sys::Guestfs;
7176
7177  my $h = Sys::Guestfs->new ();
7178  $h->add_drive ('guest.img');
7179  $h->launch ();
7180  $h->wait_ready ();
7181  $h->mount ('/dev/sda1', '/');
7182  $h->touch ('/hello');
7183  $h->sync ();
7184
7185 =head1 DESCRIPTION
7186
7187 The C<Sys::Guestfs> module provides a Perl XS binding to the
7188 libguestfs API for examining and modifying virtual machine
7189 disk images.
7190
7191 Amongst the things this is good for: making batch configuration
7192 changes to guests, getting disk used/free statistics (see also:
7193 virt-df), migrating between virtualization systems (see also:
7194 virt-p2v), performing partial backups, performing partial guest
7195 clones, cloning guests and changing registry/UUID/hostname info, and
7196 much else besides.
7197
7198 Libguestfs uses Linux kernel and qemu code, and can access any type of
7199 guest filesystem that Linux and qemu can, including but not limited
7200 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7201 schemes, qcow, qcow2, vmdk.
7202
7203 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7204 LVs, what filesystem is in each LV, etc.).  It can also run commands
7205 in the context of the guest.  Also you can access filesystems over FTP.
7206
7207 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7208 functions for using libguestfs from Perl, including integration
7209 with libvirt.
7210
7211 =head1 ERRORS
7212
7213 All errors turn into calls to C<croak> (see L<Carp(3)>).
7214
7215 =head1 METHODS
7216
7217 =over 4
7218
7219 =cut
7220
7221 package Sys::Guestfs;
7222
7223 use strict;
7224 use warnings;
7225
7226 require XSLoader;
7227 XSLoader::load ('Sys::Guestfs');
7228
7229 =item $h = Sys::Guestfs->new ();
7230
7231 Create a new guestfs handle.
7232
7233 =cut
7234
7235 sub new {
7236   my $proto = shift;
7237   my $class = ref ($proto) || $proto;
7238
7239   my $self = Sys::Guestfs::_create ();
7240   bless $self, $class;
7241   return $self;
7242 }
7243
7244 ";
7245
7246   (* Actions.  We only need to print documentation for these as
7247    * they are pulled in from the XS code automatically.
7248    *)
7249   List.iter (
7250     fun (name, style, _, flags, _, _, longdesc) ->
7251       if not (List.mem NotInDocs flags) then (
7252         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7253         pr "=item ";
7254         generate_perl_prototype name style;
7255         pr "\n\n";
7256         pr "%s\n\n" longdesc;
7257         if List.mem ProtocolLimitWarning flags then
7258           pr "%s\n\n" protocol_limit_warning;
7259         if List.mem DangerWillRobinson flags then
7260           pr "%s\n\n" danger_will_robinson;
7261         match deprecation_notice flags with
7262         | None -> ()
7263         | Some txt -> pr "%s\n\n" txt
7264       )
7265   ) all_functions_sorted;
7266
7267   (* End of file. *)
7268   pr "\
7269 =cut
7270
7271 1;
7272
7273 =back
7274
7275 =head1 COPYRIGHT
7276
7277 Copyright (C) 2009 Red Hat Inc.
7278
7279 =head1 LICENSE
7280
7281 Please see the file COPYING.LIB for the full license.
7282
7283 =head1 SEE ALSO
7284
7285 L<guestfs(3)>,
7286 L<guestfish(1)>,
7287 L<http://libguestfs.org>,
7288 L<Sys::Guestfs::Lib(3)>.
7289
7290 =cut
7291 "
7292
7293 and generate_perl_prototype name style =
7294   (match fst style with
7295    | RErr -> ()
7296    | RBool n
7297    | RInt n
7298    | RInt64 n
7299    | RConstString n
7300    | RConstOptString n
7301    | RString n
7302    | RBufferOut n -> pr "$%s = " n
7303    | RStruct (n,_)
7304    | RHashtable n -> pr "%%%s = " n
7305    | RStringList n
7306    | RStructList (n,_) -> pr "@%s = " n
7307   );
7308   pr "$h->%s (" name;
7309   let comma = ref false in
7310   List.iter (
7311     fun arg ->
7312       if !comma then pr ", ";
7313       comma := true;
7314       match arg with
7315       | Pathname n | Device n | Dev_or_Path n | String n
7316       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7317           pr "$%s" n
7318       | StringList n ->
7319           pr "\\@%s" n
7320   ) (snd style);
7321   pr ");"
7322
7323 (* Generate Python C module. *)
7324 and generate_python_c () =
7325   generate_header CStyle LGPLv2;
7326
7327   pr "\
7328 #include <stdio.h>
7329 #include <stdlib.h>
7330 #include <assert.h>
7331
7332 #include <Python.h>
7333
7334 #include \"guestfs.h\"
7335
7336 typedef struct {
7337   PyObject_HEAD
7338   guestfs_h *g;
7339 } Pyguestfs_Object;
7340
7341 static guestfs_h *
7342 get_handle (PyObject *obj)
7343 {
7344   assert (obj);
7345   assert (obj != Py_None);
7346   return ((Pyguestfs_Object *) obj)->g;
7347 }
7348
7349 static PyObject *
7350 put_handle (guestfs_h *g)
7351 {
7352   assert (g);
7353   return
7354     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7355 }
7356
7357 /* This list should be freed (but not the strings) after use. */
7358 static const char **
7359 get_string_list (PyObject *obj)
7360 {
7361   int i, len;
7362   const char **r;
7363
7364   assert (obj);
7365
7366   if (!PyList_Check (obj)) {
7367     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7368     return NULL;
7369   }
7370
7371   len = PyList_Size (obj);
7372   r = malloc (sizeof (char *) * (len+1));
7373   if (r == NULL) {
7374     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7375     return NULL;
7376   }
7377
7378   for (i = 0; i < len; ++i)
7379     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7380   r[len] = NULL;
7381
7382   return r;
7383 }
7384
7385 static PyObject *
7386 put_string_list (char * const * const argv)
7387 {
7388   PyObject *list;
7389   int argc, i;
7390
7391   for (argc = 0; argv[argc] != NULL; ++argc)
7392     ;
7393
7394   list = PyList_New (argc);
7395   for (i = 0; i < argc; ++i)
7396     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7397
7398   return list;
7399 }
7400
7401 static PyObject *
7402 put_table (char * const * const argv)
7403 {
7404   PyObject *list, *item;
7405   int argc, i;
7406
7407   for (argc = 0; argv[argc] != NULL; ++argc)
7408     ;
7409
7410   list = PyList_New (argc >> 1);
7411   for (i = 0; i < argc; i += 2) {
7412     item = PyTuple_New (2);
7413     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7414     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7415     PyList_SetItem (list, i >> 1, item);
7416   }
7417
7418   return list;
7419 }
7420
7421 static void
7422 free_strings (char **argv)
7423 {
7424   int argc;
7425
7426   for (argc = 0; argv[argc] != NULL; ++argc)
7427     free (argv[argc]);
7428   free (argv);
7429 }
7430
7431 static PyObject *
7432 py_guestfs_create (PyObject *self, PyObject *args)
7433 {
7434   guestfs_h *g;
7435
7436   g = guestfs_create ();
7437   if (g == NULL) {
7438     PyErr_SetString (PyExc_RuntimeError,
7439                      \"guestfs.create: failed to allocate handle\");
7440     return NULL;
7441   }
7442   guestfs_set_error_handler (g, NULL, NULL);
7443   return put_handle (g);
7444 }
7445
7446 static PyObject *
7447 py_guestfs_close (PyObject *self, PyObject *args)
7448 {
7449   PyObject *py_g;
7450   guestfs_h *g;
7451
7452   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7453     return NULL;
7454   g = get_handle (py_g);
7455
7456   guestfs_close (g);
7457
7458   Py_INCREF (Py_None);
7459   return Py_None;
7460 }
7461
7462 ";
7463
7464   let emit_put_list_function typ =
7465     pr "static PyObject *\n";
7466     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7467     pr "{\n";
7468     pr "  PyObject *list;\n";
7469     pr "  int i;\n";
7470     pr "\n";
7471     pr "  list = PyList_New (%ss->len);\n" typ;
7472     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7473     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7474     pr "  return list;\n";
7475     pr "};\n";
7476     pr "\n"
7477   in
7478
7479   (* Structures, turned into Python dictionaries. *)
7480   List.iter (
7481     fun (typ, cols) ->
7482       pr "static PyObject *\n";
7483       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7484       pr "{\n";
7485       pr "  PyObject *dict;\n";
7486       pr "\n";
7487       pr "  dict = PyDict_New ();\n";
7488       List.iter (
7489         function
7490         | name, FString ->
7491             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7492             pr "                        PyString_FromString (%s->%s));\n"
7493               typ name
7494         | name, FBuffer ->
7495             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7496             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7497               typ name typ name
7498         | name, FUUID ->
7499             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7500             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7501               typ name
7502         | name, (FBytes|FUInt64) ->
7503             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7504             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7505               typ name
7506         | name, FInt64 ->
7507             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7508             pr "                        PyLong_FromLongLong (%s->%s));\n"
7509               typ name
7510         | name, FUInt32 ->
7511             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7512             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7513               typ name
7514         | name, FInt32 ->
7515             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7516             pr "                        PyLong_FromLong (%s->%s));\n"
7517               typ name
7518         | name, FOptPercent ->
7519             pr "  if (%s->%s >= 0)\n" typ name;
7520             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7521             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7522               typ name;
7523             pr "  else {\n";
7524             pr "    Py_INCREF (Py_None);\n";
7525             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);" name;
7526             pr "  }\n"
7527         | name, FChar ->
7528             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7529             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7530       ) cols;
7531       pr "  return dict;\n";
7532       pr "};\n";
7533       pr "\n";
7534
7535   ) structs;
7536
7537   (* Emit a put_TYPE_list function definition only if that function is used. *)
7538   List.iter (
7539     function
7540     | typ, (RStructListOnly | RStructAndList) ->
7541         (* generate the function for typ *)
7542         emit_put_list_function typ
7543     | typ, _ -> () (* empty *)
7544   ) rstructs_used;
7545
7546   (* Python wrapper functions. *)
7547   List.iter (
7548     fun (name, style, _, _, _, _, _) ->
7549       pr "static PyObject *\n";
7550       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7551       pr "{\n";
7552
7553       pr "  PyObject *py_g;\n";
7554       pr "  guestfs_h *g;\n";
7555       pr "  PyObject *py_r;\n";
7556
7557       let error_code =
7558         match fst style with
7559         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7560         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7561         | RConstString _ | RConstOptString _ ->
7562             pr "  const char *r;\n"; "NULL"
7563         | RString _ -> pr "  char *r;\n"; "NULL"
7564         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7565         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7566         | RStructList (_, typ) ->
7567             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7568         | RBufferOut _ ->
7569             pr "  char *r;\n";
7570             pr "  size_t size;\n";
7571             "NULL" in
7572
7573       List.iter (
7574         function
7575         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7576             pr "  const char *%s;\n" n
7577         | OptString n -> pr "  const char *%s;\n" n
7578         | StringList n ->
7579             pr "  PyObject *py_%s;\n" n;
7580             pr "  const char **%s;\n" n
7581         | Bool n -> pr "  int %s;\n" n
7582         | Int n -> pr "  int %s;\n" n
7583       ) (snd style);
7584
7585       pr "\n";
7586
7587       (* Convert the parameters. *)
7588       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7589       List.iter (
7590         function
7591         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7592         | OptString _ -> pr "z"
7593         | StringList _ -> pr "O"
7594         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7595         | Int _ -> pr "i"
7596       ) (snd style);
7597       pr ":guestfs_%s\",\n" name;
7598       pr "                         &py_g";
7599       List.iter (
7600         function
7601         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7602         | OptString n -> pr ", &%s" n
7603         | StringList n -> pr ", &py_%s" n
7604         | Bool n -> pr ", &%s" n
7605         | Int n -> pr ", &%s" n
7606       ) (snd style);
7607
7608       pr "))\n";
7609       pr "    return NULL;\n";
7610
7611       pr "  g = get_handle (py_g);\n";
7612       List.iter (
7613         function
7614         | Pathname _ | Device _ | Dev_or_Path _ | String _
7615         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7616         | StringList n ->
7617             pr "  %s = get_string_list (py_%s);\n" n n;
7618             pr "  if (!%s) return NULL;\n" n
7619       ) (snd style);
7620
7621       pr "\n";
7622
7623       pr "  r = guestfs_%s " name;
7624       generate_c_call_args ~handle:"g" style;
7625       pr ";\n";
7626
7627       List.iter (
7628         function
7629         | Pathname _ | Device _ | Dev_or_Path _ | String _
7630         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7631         | StringList n ->
7632             pr "  free (%s);\n" n
7633       ) (snd style);
7634
7635       pr "  if (r == %s) {\n" error_code;
7636       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7637       pr "    return NULL;\n";
7638       pr "  }\n";
7639       pr "\n";
7640
7641       (match fst style with
7642        | RErr ->
7643            pr "  Py_INCREF (Py_None);\n";
7644            pr "  py_r = Py_None;\n"
7645        | RInt _
7646        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7647        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7648        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7649        | RConstOptString _ ->
7650            pr "  if (r)\n";
7651            pr "    py_r = PyString_FromString (r);\n";
7652            pr "  else {\n";
7653            pr "    Py_INCREF (Py_None);\n";
7654            pr "    py_r = Py_None;\n";
7655            pr "  }\n"
7656        | RString _ ->
7657            pr "  py_r = PyString_FromString (r);\n";
7658            pr "  free (r);\n"
7659        | RStringList _ ->
7660            pr "  py_r = put_string_list (r);\n";
7661            pr "  free_strings (r);\n"
7662        | RStruct (_, typ) ->
7663            pr "  py_r = put_%s (r);\n" typ;
7664            pr "  guestfs_free_%s (r);\n" typ
7665        | RStructList (_, typ) ->
7666            pr "  py_r = put_%s_list (r);\n" typ;
7667            pr "  guestfs_free_%s_list (r);\n" typ
7668        | RHashtable n ->
7669            pr "  py_r = put_table (r);\n";
7670            pr "  free_strings (r);\n"
7671        | RBufferOut _ ->
7672            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7673            pr "  free (r);\n"
7674       );
7675
7676       pr "  return py_r;\n";
7677       pr "}\n";
7678       pr "\n"
7679   ) all_functions;
7680
7681   (* Table of functions. *)
7682   pr "static PyMethodDef methods[] = {\n";
7683   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7684   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7685   List.iter (
7686     fun (name, _, _, _, _, _, _) ->
7687       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7688         name name
7689   ) all_functions;
7690   pr "  { NULL, NULL, 0, NULL }\n";
7691   pr "};\n";
7692   pr "\n";
7693
7694   (* Init function. *)
7695   pr "\
7696 void
7697 initlibguestfsmod (void)
7698 {
7699   static int initialized = 0;
7700
7701   if (initialized) return;
7702   Py_InitModule ((char *) \"libguestfsmod\", methods);
7703   initialized = 1;
7704 }
7705 "
7706
7707 (* Generate Python module. *)
7708 and generate_python_py () =
7709   generate_header HashStyle LGPLv2;
7710
7711   pr "\
7712 u\"\"\"Python bindings for libguestfs
7713
7714 import guestfs
7715 g = guestfs.GuestFS ()
7716 g.add_drive (\"guest.img\")
7717 g.launch ()
7718 g.wait_ready ()
7719 parts = g.list_partitions ()
7720
7721 The guestfs module provides a Python binding to the libguestfs API
7722 for examining and modifying virtual machine disk images.
7723
7724 Amongst the things this is good for: making batch configuration
7725 changes to guests, getting disk used/free statistics (see also:
7726 virt-df), migrating between virtualization systems (see also:
7727 virt-p2v), performing partial backups, performing partial guest
7728 clones, cloning guests and changing registry/UUID/hostname info, and
7729 much else besides.
7730
7731 Libguestfs uses Linux kernel and qemu code, and can access any type of
7732 guest filesystem that Linux and qemu can, including but not limited
7733 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7734 schemes, qcow, qcow2, vmdk.
7735
7736 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7737 LVs, what filesystem is in each LV, etc.).  It can also run commands
7738 in the context of the guest.  Also you can access filesystems over FTP.
7739
7740 Errors which happen while using the API are turned into Python
7741 RuntimeError exceptions.
7742
7743 To create a guestfs handle you usually have to perform the following
7744 sequence of calls:
7745
7746 # Create the handle, call add_drive at least once, and possibly
7747 # several times if the guest has multiple block devices:
7748 g = guestfs.GuestFS ()
7749 g.add_drive (\"guest.img\")
7750
7751 # Launch the qemu subprocess and wait for it to become ready:
7752 g.launch ()
7753 g.wait_ready ()
7754
7755 # Now you can issue commands, for example:
7756 logvols = g.lvs ()
7757
7758 \"\"\"
7759
7760 import libguestfsmod
7761
7762 class GuestFS:
7763     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
7764
7765     def __init__ (self):
7766         \"\"\"Create a new libguestfs handle.\"\"\"
7767         self._o = libguestfsmod.create ()
7768
7769     def __del__ (self):
7770         libguestfsmod.close (self._o)
7771
7772 ";
7773
7774   List.iter (
7775     fun (name, style, _, flags, _, _, longdesc) ->
7776       pr "    def %s " name;
7777       generate_py_call_args ~handle:"self" (snd style);
7778       pr ":\n";
7779
7780       if not (List.mem NotInDocs flags) then (
7781         let doc = replace_str longdesc "C<guestfs_" "C<g." in
7782         let doc =
7783           match fst style with
7784           | RErr | RInt _ | RInt64 _ | RBool _
7785           | RConstOptString _ | RConstString _
7786           | RString _ | RBufferOut _ -> doc
7787           | RStringList _ ->
7788               doc ^ "\n\nThis function returns a list of strings."
7789           | RStruct (_, typ) ->
7790               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
7791           | RStructList (_, typ) ->
7792               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
7793           | RHashtable _ ->
7794               doc ^ "\n\nThis function returns a dictionary." in
7795         let doc =
7796           if List.mem ProtocolLimitWarning flags then
7797             doc ^ "\n\n" ^ protocol_limit_warning
7798           else doc in
7799         let doc =
7800           if List.mem DangerWillRobinson flags then
7801             doc ^ "\n\n" ^ danger_will_robinson
7802           else doc in
7803         let doc =
7804           match deprecation_notice flags with
7805           | None -> doc
7806           | Some txt -> doc ^ "\n\n" ^ txt in
7807         let doc = pod2text ~width:60 name doc in
7808         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
7809         let doc = String.concat "\n        " doc in
7810         pr "        u\"\"\"%s\"\"\"\n" doc;
7811       );
7812       pr "        return libguestfsmod.%s " name;
7813       generate_py_call_args ~handle:"self._o" (snd style);
7814       pr "\n";
7815       pr "\n";
7816   ) all_functions
7817
7818 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
7819 and generate_py_call_args ~handle args =
7820   pr "(%s" handle;
7821   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
7822   pr ")"
7823
7824 (* Useful if you need the longdesc POD text as plain text.  Returns a
7825  * list of lines.
7826  *
7827  * Because this is very slow (the slowest part of autogeneration),
7828  * we memoize the results.
7829  *)
7830 and pod2text ~width name longdesc =
7831   let key = width, name, longdesc in
7832   try Hashtbl.find pod2text_memo key
7833   with Not_found ->
7834     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
7835     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
7836     close_out chan;
7837     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
7838     let chan = Unix.open_process_in cmd in
7839     let lines = ref [] in
7840     let rec loop i =
7841       let line = input_line chan in
7842       if i = 1 then             (* discard the first line of output *)
7843         loop (i+1)
7844       else (
7845         let line = triml line in
7846         lines := line :: !lines;
7847         loop (i+1)
7848       ) in
7849     let lines = try loop 1 with End_of_file -> List.rev !lines in
7850     Unix.unlink filename;
7851     (match Unix.close_process_in chan with
7852      | Unix.WEXITED 0 -> ()
7853      | Unix.WEXITED i ->
7854          failwithf "pod2text: process exited with non-zero status (%d)" i
7855      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
7856          failwithf "pod2text: process signalled or stopped by signal %d" i
7857     );
7858     Hashtbl.add pod2text_memo key lines;
7859     let chan = open_out pod2text_memo_filename in
7860     output_value chan pod2text_memo;
7861     close_out chan;
7862     lines
7863
7864 (* Generate ruby bindings. *)
7865 and generate_ruby_c () =
7866   generate_header CStyle LGPLv2;
7867
7868   pr "\
7869 #include <stdio.h>
7870 #include <stdlib.h>
7871
7872 #include <ruby.h>
7873
7874 #include \"guestfs.h\"
7875
7876 #include \"extconf.h\"
7877
7878 /* For Ruby < 1.9 */
7879 #ifndef RARRAY_LEN
7880 #define RARRAY_LEN(r) (RARRAY((r))->len)
7881 #endif
7882
7883 static VALUE m_guestfs;                 /* guestfs module */
7884 static VALUE c_guestfs;                 /* guestfs_h handle */
7885 static VALUE e_Error;                   /* used for all errors */
7886
7887 static void ruby_guestfs_free (void *p)
7888 {
7889   if (!p) return;
7890   guestfs_close ((guestfs_h *) p);
7891 }
7892
7893 static VALUE ruby_guestfs_create (VALUE m)
7894 {
7895   guestfs_h *g;
7896
7897   g = guestfs_create ();
7898   if (!g)
7899     rb_raise (e_Error, \"failed to create guestfs handle\");
7900
7901   /* Don't print error messages to stderr by default. */
7902   guestfs_set_error_handler (g, NULL, NULL);
7903
7904   /* Wrap it, and make sure the close function is called when the
7905    * handle goes away.
7906    */
7907   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
7908 }
7909
7910 static VALUE ruby_guestfs_close (VALUE gv)
7911 {
7912   guestfs_h *g;
7913   Data_Get_Struct (gv, guestfs_h, g);
7914
7915   ruby_guestfs_free (g);
7916   DATA_PTR (gv) = NULL;
7917
7918   return Qnil;
7919 }
7920
7921 ";
7922
7923   List.iter (
7924     fun (name, style, _, _, _, _, _) ->
7925       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
7926       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
7927       pr ")\n";
7928       pr "{\n";
7929       pr "  guestfs_h *g;\n";
7930       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
7931       pr "  if (!g)\n";
7932       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
7933         name;
7934       pr "\n";
7935
7936       List.iter (
7937         function
7938         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7939             pr "  Check_Type (%sv, T_STRING);\n" n;
7940             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
7941             pr "  if (!%s)\n" n;
7942             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
7943             pr "              \"%s\", \"%s\");\n" n name
7944         | OptString n ->
7945             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
7946         | StringList n ->
7947             pr "  char **%s;\n" n;
7948             pr "  Check_Type (%sv, T_ARRAY);\n" n;
7949             pr "  {\n";
7950             pr "    int i, len;\n";
7951             pr "    len = RARRAY_LEN (%sv);\n" n;
7952             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
7953               n;
7954             pr "    for (i = 0; i < len; ++i) {\n";
7955             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
7956             pr "      %s[i] = StringValueCStr (v);\n" n;
7957             pr "    }\n";
7958             pr "    %s[len] = NULL;\n" n;
7959             pr "  }\n";
7960         | Bool n ->
7961             pr "  int %s = RTEST (%sv);\n" n n
7962         | Int n ->
7963             pr "  int %s = NUM2INT (%sv);\n" n n
7964       ) (snd style);
7965       pr "\n";
7966
7967       let error_code =
7968         match fst style with
7969         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7970         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7971         | RConstString _ | RConstOptString _ ->
7972             pr "  const char *r;\n"; "NULL"
7973         | RString _ -> pr "  char *r;\n"; "NULL"
7974         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7975         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7976         | RStructList (_, typ) ->
7977             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7978         | RBufferOut _ ->
7979             pr "  char *r;\n";
7980             pr "  size_t size;\n";
7981             "NULL" in
7982       pr "\n";
7983
7984       pr "  r = guestfs_%s " name;
7985       generate_c_call_args ~handle:"g" style;
7986       pr ";\n";
7987
7988       List.iter (
7989         function
7990         | Pathname _ | Device _ | Dev_or_Path _ | String _
7991         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7992         | StringList n ->
7993             pr "  free (%s);\n" n
7994       ) (snd style);
7995
7996       pr "  if (r == %s)\n" error_code;
7997       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
7998       pr "\n";
7999
8000       (match fst style with
8001        | RErr ->
8002            pr "  return Qnil;\n"
8003        | RInt _ | RBool _ ->
8004            pr "  return INT2NUM (r);\n"
8005        | RInt64 _ ->
8006            pr "  return ULL2NUM (r);\n"
8007        | RConstString _ ->
8008            pr "  return rb_str_new2 (r);\n";
8009        | RConstOptString _ ->
8010            pr "  if (r)\n";
8011            pr "    return rb_str_new2 (r);\n";
8012            pr "  else\n";
8013            pr "    return Qnil;\n";
8014        | RString _ ->
8015            pr "  VALUE rv = rb_str_new2 (r);\n";
8016            pr "  free (r);\n";
8017            pr "  return rv;\n";
8018        | RStringList _ ->
8019            pr "  int i, len = 0;\n";
8020            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8021            pr "  VALUE rv = rb_ary_new2 (len);\n";
8022            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8023            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8024            pr "    free (r[i]);\n";
8025            pr "  }\n";
8026            pr "  free (r);\n";
8027            pr "  return rv;\n"
8028        | RStruct (_, typ) ->
8029            let cols = cols_of_struct typ in
8030            generate_ruby_struct_code typ cols
8031        | RStructList (_, typ) ->
8032            let cols = cols_of_struct typ in
8033            generate_ruby_struct_list_code typ cols
8034        | RHashtable _ ->
8035            pr "  VALUE rv = rb_hash_new ();\n";
8036            pr "  int i;\n";
8037            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8038            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8039            pr "    free (r[i]);\n";
8040            pr "    free (r[i+1]);\n";
8041            pr "  }\n";
8042            pr "  free (r);\n";
8043            pr "  return rv;\n"
8044        | RBufferOut _ ->
8045            pr "  VALUE rv = rb_str_new (r, size);\n";
8046            pr "  free (r);\n";
8047            pr "  return rv;\n";
8048       );
8049
8050       pr "}\n";
8051       pr "\n"
8052   ) all_functions;
8053
8054   pr "\
8055 /* Initialize the module. */
8056 void Init__guestfs ()
8057 {
8058   m_guestfs = rb_define_module (\"Guestfs\");
8059   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8060   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8061
8062   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8063   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8064
8065 ";
8066   (* Define the rest of the methods. *)
8067   List.iter (
8068     fun (name, style, _, _, _, _, _) ->
8069       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8070       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8071   ) all_functions;
8072
8073   pr "}\n"
8074
8075 (* Ruby code to return a struct. *)
8076 and generate_ruby_struct_code typ cols =
8077   pr "  VALUE rv = rb_hash_new ();\n";
8078   List.iter (
8079     function
8080     | name, FString ->
8081         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8082     | name, FBuffer ->
8083         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8084     | name, FUUID ->
8085         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8086     | name, (FBytes|FUInt64) ->
8087         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8088     | name, FInt64 ->
8089         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8090     | name, FUInt32 ->
8091         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8092     | name, FInt32 ->
8093         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8094     | name, FOptPercent ->
8095         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8096     | name, FChar -> (* XXX wrong? *)
8097         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8098   ) cols;
8099   pr "  guestfs_free_%s (r);\n" typ;
8100   pr "  return rv;\n"
8101
8102 (* Ruby code to return a struct list. *)
8103 and generate_ruby_struct_list_code typ cols =
8104   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8105   pr "  int i;\n";
8106   pr "  for (i = 0; i < r->len; ++i) {\n";
8107   pr "    VALUE hv = rb_hash_new ();\n";
8108   List.iter (
8109     function
8110     | name, FString ->
8111         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8112     | name, FBuffer ->
8113         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
8114     | name, FUUID ->
8115         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8116     | name, (FBytes|FUInt64) ->
8117         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8118     | name, FInt64 ->
8119         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8120     | name, FUInt32 ->
8121         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8122     | name, FInt32 ->
8123         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8124     | name, FOptPercent ->
8125         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8126     | name, FChar -> (* XXX wrong? *)
8127         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8128   ) cols;
8129   pr "    rb_ary_push (rv, hv);\n";
8130   pr "  }\n";
8131   pr "  guestfs_free_%s_list (r);\n" typ;
8132   pr "  return rv;\n"
8133
8134 (* Generate Java bindings GuestFS.java file. *)
8135 and generate_java_java () =
8136   generate_header CStyle LGPLv2;
8137
8138   pr "\
8139 package com.redhat.et.libguestfs;
8140
8141 import java.util.HashMap;
8142 import com.redhat.et.libguestfs.LibGuestFSException;
8143 import com.redhat.et.libguestfs.PV;
8144 import com.redhat.et.libguestfs.VG;
8145 import com.redhat.et.libguestfs.LV;
8146 import com.redhat.et.libguestfs.Stat;
8147 import com.redhat.et.libguestfs.StatVFS;
8148 import com.redhat.et.libguestfs.IntBool;
8149 import com.redhat.et.libguestfs.Dirent;
8150
8151 /**
8152  * The GuestFS object is a libguestfs handle.
8153  *
8154  * @author rjones
8155  */
8156 public class GuestFS {
8157   // Load the native code.
8158   static {
8159     System.loadLibrary (\"guestfs_jni\");
8160   }
8161
8162   /**
8163    * The native guestfs_h pointer.
8164    */
8165   long g;
8166
8167   /**
8168    * Create a libguestfs handle.
8169    *
8170    * @throws LibGuestFSException
8171    */
8172   public GuestFS () throws LibGuestFSException
8173   {
8174     g = _create ();
8175   }
8176   private native long _create () throws LibGuestFSException;
8177
8178   /**
8179    * Close a libguestfs handle.
8180    *
8181    * You can also leave handles to be collected by the garbage
8182    * collector, but this method ensures that the resources used
8183    * by the handle are freed up immediately.  If you call any
8184    * other methods after closing the handle, you will get an
8185    * exception.
8186    *
8187    * @throws LibGuestFSException
8188    */
8189   public void close () throws LibGuestFSException
8190   {
8191     if (g != 0)
8192       _close (g);
8193     g = 0;
8194   }
8195   private native void _close (long g) throws LibGuestFSException;
8196
8197   public void finalize () throws LibGuestFSException
8198   {
8199     close ();
8200   }
8201
8202 ";
8203
8204   List.iter (
8205     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8206       if not (List.mem NotInDocs flags); then (
8207         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8208         let doc =
8209           if List.mem ProtocolLimitWarning flags then
8210             doc ^ "\n\n" ^ protocol_limit_warning
8211           else doc in
8212         let doc =
8213           if List.mem DangerWillRobinson flags then
8214             doc ^ "\n\n" ^ danger_will_robinson
8215           else doc in
8216         let doc =
8217           match deprecation_notice flags with
8218           | None -> doc
8219           | Some txt -> doc ^ "\n\n" ^ txt in
8220         let doc = pod2text ~width:60 name doc in
8221         let doc = List.map (            (* RHBZ#501883 *)
8222           function
8223           | "" -> "<p>"
8224           | nonempty -> nonempty
8225         ) doc in
8226         let doc = String.concat "\n   * " doc in
8227
8228         pr "  /**\n";
8229         pr "   * %s\n" shortdesc;
8230         pr "   * <p>\n";
8231         pr "   * %s\n" doc;
8232         pr "   * @throws LibGuestFSException\n";
8233         pr "   */\n";
8234         pr "  ";
8235       );
8236       generate_java_prototype ~public:true ~semicolon:false name style;
8237       pr "\n";
8238       pr "  {\n";
8239       pr "    if (g == 0)\n";
8240       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8241         name;
8242       pr "    ";
8243       if fst style <> RErr then pr "return ";
8244       pr "_%s " name;
8245       generate_java_call_args ~handle:"g" (snd style);
8246       pr ";\n";
8247       pr "  }\n";
8248       pr "  ";
8249       generate_java_prototype ~privat:true ~native:true name style;
8250       pr "\n";
8251       pr "\n";
8252   ) all_functions;
8253
8254   pr "}\n"
8255
8256 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8257 and generate_java_call_args ~handle args =
8258   pr "(%s" handle;
8259   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8260   pr ")"
8261
8262 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8263     ?(semicolon=true) name style =
8264   if privat then pr "private ";
8265   if public then pr "public ";
8266   if native then pr "native ";
8267
8268   (* return type *)
8269   (match fst style with
8270    | RErr -> pr "void ";
8271    | RInt _ -> pr "int ";
8272    | RInt64 _ -> pr "long ";
8273    | RBool _ -> pr "boolean ";
8274    | RConstString _ | RConstOptString _ | RString _
8275    | RBufferOut _ -> pr "String ";
8276    | RStringList _ -> pr "String[] ";
8277    | RStruct (_, typ) ->
8278        let name = java_name_of_struct typ in
8279        pr "%s " name;
8280    | RStructList (_, typ) ->
8281        let name = java_name_of_struct typ in
8282        pr "%s[] " name;
8283    | RHashtable _ -> pr "HashMap<String,String> ";
8284   );
8285
8286   if native then pr "_%s " name else pr "%s " name;
8287   pr "(";
8288   let needs_comma = ref false in
8289   if native then (
8290     pr "long g";
8291     needs_comma := true
8292   );
8293
8294   (* args *)
8295   List.iter (
8296     fun arg ->
8297       if !needs_comma then pr ", ";
8298       needs_comma := true;
8299
8300       match arg with
8301       | Pathname n
8302       | Device n | Dev_or_Path n
8303       | String n
8304       | OptString n
8305       | FileIn n
8306       | FileOut n ->
8307           pr "String %s" n
8308       | StringList n ->
8309           pr "String[] %s" n
8310       | Bool n ->
8311           pr "boolean %s" n
8312       | Int n ->
8313           pr "int %s" n
8314   ) (snd style);
8315
8316   pr ")\n";
8317   pr "    throws LibGuestFSException";
8318   if semicolon then pr ";"
8319
8320 and generate_java_struct jtyp cols =
8321   generate_header CStyle LGPLv2;
8322
8323   pr "\
8324 package com.redhat.et.libguestfs;
8325
8326 /**
8327  * Libguestfs %s structure.
8328  *
8329  * @author rjones
8330  * @see GuestFS
8331  */
8332 public class %s {
8333 " jtyp jtyp;
8334
8335   List.iter (
8336     function
8337     | name, FString
8338     | name, FUUID
8339     | name, FBuffer -> pr "  public String %s;\n" name
8340     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8341     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8342     | name, FChar -> pr "  public char %s;\n" name
8343     | name, FOptPercent ->
8344         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8345         pr "  public float %s;\n" name
8346   ) cols;
8347
8348   pr "}\n"
8349
8350 and generate_java_c () =
8351   generate_header CStyle LGPLv2;
8352
8353   pr "\
8354 #include <stdio.h>
8355 #include <stdlib.h>
8356 #include <string.h>
8357
8358 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8359 #include \"guestfs.h\"
8360
8361 /* Note that this function returns.  The exception is not thrown
8362  * until after the wrapper function returns.
8363  */
8364 static void
8365 throw_exception (JNIEnv *env, const char *msg)
8366 {
8367   jclass cl;
8368   cl = (*env)->FindClass (env,
8369                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8370   (*env)->ThrowNew (env, cl, msg);
8371 }
8372
8373 JNIEXPORT jlong JNICALL
8374 Java_com_redhat_et_libguestfs_GuestFS__1create
8375   (JNIEnv *env, jobject obj)
8376 {
8377   guestfs_h *g;
8378
8379   g = guestfs_create ();
8380   if (g == NULL) {
8381     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8382     return 0;
8383   }
8384   guestfs_set_error_handler (g, NULL, NULL);
8385   return (jlong) (long) g;
8386 }
8387
8388 JNIEXPORT void JNICALL
8389 Java_com_redhat_et_libguestfs_GuestFS__1close
8390   (JNIEnv *env, jobject obj, jlong jg)
8391 {
8392   guestfs_h *g = (guestfs_h *) (long) jg;
8393   guestfs_close (g);
8394 }
8395
8396 ";
8397
8398   List.iter (
8399     fun (name, style, _, _, _, _, _) ->
8400       pr "JNIEXPORT ";
8401       (match fst style with
8402        | RErr -> pr "void ";
8403        | RInt _ -> pr "jint ";
8404        | RInt64 _ -> pr "jlong ";
8405        | RBool _ -> pr "jboolean ";
8406        | RConstString _ | RConstOptString _ | RString _
8407        | RBufferOut _ -> pr "jstring ";
8408        | RStruct _ | RHashtable _ ->
8409            pr "jobject ";
8410        | RStringList _ | RStructList _ ->
8411            pr "jobjectArray ";
8412       );
8413       pr "JNICALL\n";
8414       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8415       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8416       pr "\n";
8417       pr "  (JNIEnv *env, jobject obj, jlong jg";
8418       List.iter (
8419         function
8420         | Pathname n
8421         | Device n | Dev_or_Path n
8422         | String n
8423         | OptString n
8424         | FileIn n
8425         | FileOut n ->
8426             pr ", jstring j%s" n
8427         | StringList n ->
8428             pr ", jobjectArray j%s" n
8429         | Bool n ->
8430             pr ", jboolean j%s" n
8431         | Int n ->
8432             pr ", jint j%s" n
8433       ) (snd style);
8434       pr ")\n";
8435       pr "{\n";
8436       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8437       let error_code, no_ret =
8438         match fst style with
8439         | RErr -> pr "  int r;\n"; "-1", ""
8440         | RBool _
8441         | RInt _ -> pr "  int r;\n"; "-1", "0"
8442         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8443         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8444         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8445         | RString _ ->
8446             pr "  jstring jr;\n";
8447             pr "  char *r;\n"; "NULL", "NULL"
8448         | RStringList _ ->
8449             pr "  jobjectArray jr;\n";
8450             pr "  int r_len;\n";
8451             pr "  jclass cl;\n";
8452             pr "  jstring jstr;\n";
8453             pr "  char **r;\n"; "NULL", "NULL"
8454         | RStruct (_, typ) ->
8455             pr "  jobject jr;\n";
8456             pr "  jclass cl;\n";
8457             pr "  jfieldID fl;\n";
8458             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8459         | RStructList (_, typ) ->
8460             pr "  jobjectArray jr;\n";
8461             pr "  jclass cl;\n";
8462             pr "  jfieldID fl;\n";
8463             pr "  jobject jfl;\n";
8464             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8465         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8466         | RBufferOut _ ->
8467             pr "  jstring jr;\n";
8468             pr "  char *r;\n";
8469             pr "  size_t size;\n";
8470             "NULL", "NULL" in
8471       List.iter (
8472         function
8473         | Pathname n
8474         | Device n | Dev_or_Path n
8475         | String n
8476         | OptString n
8477         | FileIn n
8478         | FileOut n ->
8479             pr "  const char *%s;\n" n
8480         | StringList n ->
8481             pr "  int %s_len;\n" n;
8482             pr "  const char **%s;\n" n
8483         | Bool n
8484         | Int n ->
8485             pr "  int %s;\n" n
8486       ) (snd style);
8487
8488       let needs_i =
8489         (match fst style with
8490          | RStringList _ | RStructList _ -> true
8491          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8492          | RConstOptString _
8493          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8494           List.exists (function StringList _ -> true | _ -> false) (snd style) in
8495       if needs_i then
8496         pr "  int i;\n";
8497
8498       pr "\n";
8499
8500       (* Get the parameters. *)
8501       List.iter (
8502         function
8503         | Pathname n
8504         | Device n | Dev_or_Path n
8505         | String n
8506         | FileIn n
8507         | FileOut n ->
8508             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8509         | OptString n ->
8510             (* This is completely undocumented, but Java null becomes
8511              * a NULL parameter.
8512              *)
8513             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8514         | StringList n ->
8515             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8516             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8517             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8518             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8519               n;
8520             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8521             pr "  }\n";
8522             pr "  %s[%s_len] = NULL;\n" n n;
8523         | Bool n
8524         | Int n ->
8525             pr "  %s = j%s;\n" n n
8526       ) (snd style);
8527
8528       (* Make the call. *)
8529       pr "  r = guestfs_%s " name;
8530       generate_c_call_args ~handle:"g" style;
8531       pr ";\n";
8532
8533       (* Release the parameters. *)
8534       List.iter (
8535         function
8536         | Pathname n
8537         | Device n | Dev_or_Path n
8538         | String n
8539         | FileIn n
8540         | FileOut n ->
8541             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8542         | OptString n ->
8543             pr "  if (j%s)\n" n;
8544             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8545         | StringList n ->
8546             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8547             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8548               n;
8549             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8550             pr "  }\n";
8551             pr "  free (%s);\n" n
8552         | Bool n
8553         | Int n -> ()
8554       ) (snd style);
8555
8556       (* Check for errors. *)
8557       pr "  if (r == %s) {\n" error_code;
8558       pr "    throw_exception (env, guestfs_last_error (g));\n";
8559       pr "    return %s;\n" no_ret;
8560       pr "  }\n";
8561
8562       (* Return value. *)
8563       (match fst style with
8564        | RErr -> ()
8565        | RInt _ -> pr "  return (jint) r;\n"
8566        | RBool _ -> pr "  return (jboolean) r;\n"
8567        | RInt64 _ -> pr "  return (jlong) r;\n"
8568        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8569        | RConstOptString _ ->
8570            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8571        | RString _ ->
8572            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8573            pr "  free (r);\n";
8574            pr "  return jr;\n"
8575        | RStringList _ ->
8576            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8577            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8578            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8579            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8580            pr "  for (i = 0; i < r_len; ++i) {\n";
8581            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8582            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8583            pr "    free (r[i]);\n";
8584            pr "  }\n";
8585            pr "  free (r);\n";
8586            pr "  return jr;\n"
8587        | RStruct (_, typ) ->
8588            let jtyp = java_name_of_struct typ in
8589            let cols = cols_of_struct typ in
8590            generate_java_struct_return typ jtyp cols
8591        | RStructList (_, typ) ->
8592            let jtyp = java_name_of_struct typ in
8593            let cols = cols_of_struct typ in
8594            generate_java_struct_list_return typ jtyp cols
8595        | RHashtable _ ->
8596            (* XXX *)
8597            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8598            pr "  return NULL;\n"
8599        | RBufferOut _ ->
8600            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8601            pr "  free (r);\n";
8602            pr "  return jr;\n"
8603       );
8604
8605       pr "}\n";
8606       pr "\n"
8607   ) all_functions
8608
8609 and generate_java_struct_return typ jtyp cols =
8610   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8611   pr "  jr = (*env)->AllocObject (env, cl);\n";
8612   List.iter (
8613     function
8614     | name, FString ->
8615         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8616         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8617     | name, FUUID ->
8618         pr "  {\n";
8619         pr "    char s[33];\n";
8620         pr "    memcpy (s, r->%s, 32);\n" name;
8621         pr "    s[32] = 0;\n";
8622         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8623         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8624         pr "  }\n";
8625     | name, FBuffer ->
8626         pr "  {\n";
8627         pr "    int len = r->%s_len;\n" name;
8628         pr "    char s[len+1];\n";
8629         pr "    memcpy (s, r->%s, len);\n" name;
8630         pr "    s[len] = 0;\n";
8631         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8632         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8633         pr "  }\n";
8634     | name, (FBytes|FUInt64|FInt64) ->
8635         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8636         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8637     | name, (FUInt32|FInt32) ->
8638         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8639         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8640     | name, FOptPercent ->
8641         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8642         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8643     | name, FChar ->
8644         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8645         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8646   ) cols;
8647   pr "  free (r);\n";
8648   pr "  return jr;\n"
8649
8650 and generate_java_struct_list_return typ jtyp cols =
8651   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8652   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8653   pr "  for (i = 0; i < r->len; ++i) {\n";
8654   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8655   List.iter (
8656     function
8657     | name, FString ->
8658         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8659         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8660     | name, FUUID ->
8661         pr "    {\n";
8662         pr "      char s[33];\n";
8663         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8664         pr "      s[32] = 0;\n";
8665         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8666         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8667         pr "    }\n";
8668     | name, FBuffer ->
8669         pr "    {\n";
8670         pr "      int len = r->val[i].%s_len;\n" name;
8671         pr "      char s[len+1];\n";
8672         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8673         pr "      s[len] = 0;\n";
8674         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8675         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8676         pr "    }\n";
8677     | name, (FBytes|FUInt64|FInt64) ->
8678         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8679         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8680     | name, (FUInt32|FInt32) ->
8681         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8682         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8683     | name, FOptPercent ->
8684         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8685         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8686     | name, FChar ->
8687         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8688         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8689   ) cols;
8690   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8691   pr "  }\n";
8692   pr "  guestfs_free_%s_list (r);\n" typ;
8693   pr "  return jr;\n"
8694
8695 and generate_java_makefile_inc () =
8696   generate_header HashStyle GPLv2;
8697
8698   pr "java_built_sources = \\\n";
8699   List.iter (
8700     fun (typ, jtyp) ->
8701         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8702   ) java_structs;
8703   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8704
8705 and generate_haskell_hs () =
8706   generate_header HaskellStyle LGPLv2;
8707
8708   (* XXX We only know how to generate partial FFI for Haskell
8709    * at the moment.  Please help out!
8710    *)
8711   let can_generate style =
8712     match style with
8713     | RErr, _
8714     | RInt _, _
8715     | RInt64 _, _ -> true
8716     | RBool _, _
8717     | RConstString _, _
8718     | RConstOptString _, _
8719     | RString _, _
8720     | RStringList _, _
8721     | RStruct _, _
8722     | RStructList _, _
8723     | RHashtable _, _
8724     | RBufferOut _, _ -> false in
8725
8726   pr "\
8727 {-# INCLUDE <guestfs.h> #-}
8728 {-# LANGUAGE ForeignFunctionInterface #-}
8729
8730 module Guestfs (
8731   create";
8732
8733   (* List out the names of the actions we want to export. *)
8734   List.iter (
8735     fun (name, style, _, _, _, _, _) ->
8736       if can_generate style then pr ",\n  %s" name
8737   ) all_functions;
8738
8739   pr "
8740   ) where
8741 import Foreign
8742 import Foreign.C
8743 import Foreign.C.Types
8744 import IO
8745 import Control.Exception
8746 import Data.Typeable
8747
8748 data GuestfsS = GuestfsS            -- represents the opaque C struct
8749 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
8750 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
8751
8752 -- XXX define properly later XXX
8753 data PV = PV
8754 data VG = VG
8755 data LV = LV
8756 data IntBool = IntBool
8757 data Stat = Stat
8758 data StatVFS = StatVFS
8759 data Hashtable = Hashtable
8760
8761 foreign import ccall unsafe \"guestfs_create\" c_create
8762   :: IO GuestfsP
8763 foreign import ccall unsafe \"&guestfs_close\" c_close
8764   :: FunPtr (GuestfsP -> IO ())
8765 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
8766   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
8767
8768 create :: IO GuestfsH
8769 create = do
8770   p <- c_create
8771   c_set_error_handler p nullPtr nullPtr
8772   h <- newForeignPtr c_close p
8773   return h
8774
8775 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
8776   :: GuestfsP -> IO CString
8777
8778 -- last_error :: GuestfsH -> IO (Maybe String)
8779 -- last_error h = do
8780 --   str <- withForeignPtr h (\\p -> c_last_error p)
8781 --   maybePeek peekCString str
8782
8783 last_error :: GuestfsH -> IO (String)
8784 last_error h = do
8785   str <- withForeignPtr h (\\p -> c_last_error p)
8786   if (str == nullPtr)
8787     then return \"no error\"
8788     else peekCString str
8789
8790 ";
8791
8792   (* Generate wrappers for each foreign function. *)
8793   List.iter (
8794     fun (name, style, _, _, _, _, _) ->
8795       if can_generate style then (
8796         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
8797         pr "  :: ";
8798         generate_haskell_prototype ~handle:"GuestfsP" style;
8799         pr "\n";
8800         pr "\n";
8801         pr "%s :: " name;
8802         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
8803         pr "\n";
8804         pr "%s %s = do\n" name
8805           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
8806         pr "  r <- ";
8807         (* Convert pointer arguments using with* functions. *)
8808         List.iter (
8809           function
8810           | FileIn n
8811           | FileOut n
8812           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
8813           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
8814           | StringList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
8815           | Bool _ | Int _ -> ()
8816         ) (snd style);
8817         (* Convert integer arguments. *)
8818         let args =
8819           List.map (
8820             function
8821             | Bool n -> sprintf "(fromBool %s)" n
8822             | Int n -> sprintf "(fromIntegral %s)" n
8823             | FileIn n | FileOut n
8824             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n -> n
8825           ) (snd style) in
8826         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
8827           (String.concat " " ("p" :: args));
8828         (match fst style with
8829          | RErr | RInt _ | RInt64 _ | RBool _ ->
8830              pr "  if (r == -1)\n";
8831              pr "    then do\n";
8832              pr "      err <- last_error h\n";
8833              pr "      fail err\n";
8834          | RConstString _ | RConstOptString _ | RString _
8835          | RStringList _ | RStruct _
8836          | RStructList _ | RHashtable _ | RBufferOut _ ->
8837              pr "  if (r == nullPtr)\n";
8838              pr "    then do\n";
8839              pr "      err <- last_error h\n";
8840              pr "      fail err\n";
8841         );
8842         (match fst style with
8843          | RErr ->
8844              pr "    else return ()\n"
8845          | RInt _ ->
8846              pr "    else return (fromIntegral r)\n"
8847          | RInt64 _ ->
8848              pr "    else return (fromIntegral r)\n"
8849          | RBool _ ->
8850              pr "    else return (toBool r)\n"
8851          | RConstString _
8852          | RConstOptString _
8853          | RString _
8854          | RStringList _
8855          | RStruct _
8856          | RStructList _
8857          | RHashtable _
8858          | RBufferOut _ ->
8859              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
8860         );
8861         pr "\n";
8862       )
8863   ) all_functions
8864
8865 and generate_haskell_prototype ~handle ?(hs = false) style =
8866   pr "%s -> " handle;
8867   let string = if hs then "String" else "CString" in
8868   let int = if hs then "Int" else "CInt" in
8869   let bool = if hs then "Bool" else "CInt" in
8870   let int64 = if hs then "Integer" else "Int64" in
8871   List.iter (
8872     fun arg ->
8873       (match arg with
8874        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
8875        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
8876        | StringList _ -> if hs then pr "[String]" else pr "Ptr CString"
8877        | Bool _ -> pr "%s" bool
8878        | Int _ -> pr "%s" int
8879        | FileIn _ -> pr "%s" string
8880        | FileOut _ -> pr "%s" string
8881       );
8882       pr " -> ";
8883   ) (snd style);
8884   pr "IO (";
8885   (match fst style with
8886    | RErr -> if not hs then pr "CInt"
8887    | RInt _ -> pr "%s" int
8888    | RInt64 _ -> pr "%s" int64
8889    | RBool _ -> pr "%s" bool
8890    | RConstString _ -> pr "%s" string
8891    | RConstOptString _ -> pr "Maybe %s" string
8892    | RString _ -> pr "%s" string
8893    | RStringList _ -> pr "[%s]" string
8894    | RStruct (_, typ) ->
8895        let name = java_name_of_struct typ in
8896        pr "%s" name
8897    | RStructList (_, typ) ->
8898        let name = java_name_of_struct typ in
8899        pr "[%s]" name
8900    | RHashtable _ -> pr "Hashtable"
8901    | RBufferOut _ -> pr "%s" string
8902   );
8903   pr ")"
8904
8905 and generate_bindtests () =
8906   generate_header CStyle LGPLv2;
8907
8908   pr "\
8909 #include <stdio.h>
8910 #include <stdlib.h>
8911 #include <inttypes.h>
8912 #include <string.h>
8913
8914 #include \"guestfs.h\"
8915 #include \"guestfs_protocol.h\"
8916
8917 #define error guestfs_error
8918 #define safe_calloc guestfs_safe_calloc
8919 #define safe_malloc guestfs_safe_malloc
8920
8921 static void
8922 print_strings (char * const* const argv)
8923 {
8924   int argc;
8925
8926   printf (\"[\");
8927   for (argc = 0; argv[argc] != NULL; ++argc) {
8928     if (argc > 0) printf (\", \");
8929     printf (\"\\\"%%s\\\"\", argv[argc]);
8930   }
8931   printf (\"]\\n\");
8932 }
8933
8934 /* The test0 function prints its parameters to stdout. */
8935 ";
8936
8937   let test0, tests =
8938     match test_functions with
8939     | [] -> assert false
8940     | test0 :: tests -> test0, tests in
8941
8942   let () =
8943     let (name, style, _, _, _, _, _) = test0 in
8944     generate_prototype ~extern:false ~semicolon:false ~newline:true
8945       ~handle:"g" ~prefix:"guestfs_" name style;
8946     pr "{\n";
8947     List.iter (
8948       function
8949       | Pathname n
8950       | Device n | Dev_or_Path n
8951       | String n
8952       | FileIn n
8953       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
8954       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
8955       | StringList n -> pr "  print_strings (%s);\n" n
8956       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
8957       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
8958     ) (snd style);
8959     pr "  /* Java changes stdout line buffering so we need this: */\n";
8960     pr "  fflush (stdout);\n";
8961     pr "  return 0;\n";
8962     pr "}\n";
8963     pr "\n" in
8964
8965   List.iter (
8966     fun (name, style, _, _, _, _, _) ->
8967       if String.sub name (String.length name - 3) 3 <> "err" then (
8968         pr "/* Test normal return. */\n";
8969         generate_prototype ~extern:false ~semicolon:false ~newline:true
8970           ~handle:"g" ~prefix:"guestfs_" name style;
8971         pr "{\n";
8972         (match fst style with
8973          | RErr ->
8974              pr "  return 0;\n"
8975          | RInt _ ->
8976              pr "  int r;\n";
8977              pr "  sscanf (val, \"%%d\", &r);\n";
8978              pr "  return r;\n"
8979          | RInt64 _ ->
8980              pr "  int64_t r;\n";
8981              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
8982              pr "  return r;\n"
8983          | RBool _ ->
8984              pr "  return strcmp (val, \"true\") == 0;\n"
8985          | RConstString _
8986          | RConstOptString _ ->
8987              (* Can't return the input string here.  Return a static
8988               * string so we ensure we get a segfault if the caller
8989               * tries to free it.
8990               *)
8991              pr "  return \"static string\";\n"
8992          | RString _ ->
8993              pr "  return strdup (val);\n"
8994          | RStringList _ ->
8995              pr "  char **strs;\n";
8996              pr "  int n, i;\n";
8997              pr "  sscanf (val, \"%%d\", &n);\n";
8998              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
8999              pr "  for (i = 0; i < n; ++i) {\n";
9000              pr "    strs[i] = safe_malloc (g, 16);\n";
9001              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9002              pr "  }\n";
9003              pr "  strs[n] = NULL;\n";
9004              pr "  return strs;\n"
9005          | RStruct (_, typ) ->
9006              pr "  struct guestfs_%s *r;\n" typ;
9007              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9008              pr "  return r;\n"
9009          | RStructList (_, typ) ->
9010              pr "  struct guestfs_%s_list *r;\n" typ;
9011              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9012              pr "  sscanf (val, \"%%d\", &r->len);\n";
9013              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9014              pr "  return r;\n"
9015          | RHashtable _ ->
9016              pr "  char **strs;\n";
9017              pr "  int n, i;\n";
9018              pr "  sscanf (val, \"%%d\", &n);\n";
9019              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9020              pr "  for (i = 0; i < n; ++i) {\n";
9021              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9022              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9023              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9024              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9025              pr "  }\n";
9026              pr "  strs[n*2] = NULL;\n";
9027              pr "  return strs;\n"
9028          | RBufferOut _ ->
9029              pr "  return strdup (val);\n"
9030         );
9031         pr "}\n";
9032         pr "\n"
9033       ) else (
9034         pr "/* Test error return. */\n";
9035         generate_prototype ~extern:false ~semicolon:false ~newline:true
9036           ~handle:"g" ~prefix:"guestfs_" name style;
9037         pr "{\n";
9038         pr "  error (g, \"error\");\n";
9039         (match fst style with
9040          | RErr | RInt _ | RInt64 _ | RBool _ ->
9041              pr "  return -1;\n"
9042          | RConstString _ | RConstOptString _
9043          | RString _ | RStringList _ | RStruct _
9044          | RStructList _
9045          | RHashtable _
9046          | RBufferOut _ ->
9047              pr "  return NULL;\n"
9048         );
9049         pr "}\n";
9050         pr "\n"
9051       )
9052   ) tests
9053
9054 and generate_ocaml_bindtests () =
9055   generate_header OCamlStyle GPLv2;
9056
9057   pr "\
9058 let () =
9059   let g = Guestfs.create () in
9060 ";
9061
9062   let mkargs args =
9063     String.concat " " (
9064       List.map (
9065         function
9066         | CallString s -> "\"" ^ s ^ "\""
9067         | CallOptString None -> "None"
9068         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9069         | CallStringList xs ->
9070             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9071         | CallInt i when i >= 0 -> string_of_int i
9072         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9073         | CallBool b -> string_of_bool b
9074       ) args
9075     )
9076   in
9077
9078   generate_lang_bindtests (
9079     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9080   );
9081
9082   pr "print_endline \"EOF\"\n"
9083
9084 and generate_perl_bindtests () =
9085   pr "#!/usr/bin/perl -w\n";
9086   generate_header HashStyle GPLv2;
9087
9088   pr "\
9089 use strict;
9090
9091 use Sys::Guestfs;
9092
9093 my $g = Sys::Guestfs->new ();
9094 ";
9095
9096   let mkargs args =
9097     String.concat ", " (
9098       List.map (
9099         function
9100         | CallString s -> "\"" ^ s ^ "\""
9101         | CallOptString None -> "undef"
9102         | CallOptString (Some s) -> sprintf "\"%s\"" s
9103         | CallStringList xs ->
9104             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9105         | CallInt i -> string_of_int i
9106         | CallBool b -> if b then "1" else "0"
9107       ) args
9108     )
9109   in
9110
9111   generate_lang_bindtests (
9112     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9113   );
9114
9115   pr "print \"EOF\\n\"\n"
9116
9117 and generate_python_bindtests () =
9118   generate_header HashStyle GPLv2;
9119
9120   pr "\
9121 import guestfs
9122
9123 g = guestfs.GuestFS ()
9124 ";
9125
9126   let mkargs args =
9127     String.concat ", " (
9128       List.map (
9129         function
9130         | CallString s -> "\"" ^ s ^ "\""
9131         | CallOptString None -> "None"
9132         | CallOptString (Some s) -> sprintf "\"%s\"" s
9133         | CallStringList xs ->
9134             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9135         | CallInt i -> string_of_int i
9136         | CallBool b -> if b then "1" else "0"
9137       ) args
9138     )
9139   in
9140
9141   generate_lang_bindtests (
9142     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9143   );
9144
9145   pr "print \"EOF\"\n"
9146
9147 and generate_ruby_bindtests () =
9148   generate_header HashStyle GPLv2;
9149
9150   pr "\
9151 require 'guestfs'
9152
9153 g = Guestfs::create()
9154 ";
9155
9156   let mkargs args =
9157     String.concat ", " (
9158       List.map (
9159         function
9160         | CallString s -> "\"" ^ s ^ "\""
9161         | CallOptString None -> "nil"
9162         | CallOptString (Some s) -> sprintf "\"%s\"" s
9163         | CallStringList xs ->
9164             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9165         | CallInt i -> string_of_int i
9166         | CallBool b -> string_of_bool b
9167       ) args
9168     )
9169   in
9170
9171   generate_lang_bindtests (
9172     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9173   );
9174
9175   pr "print \"EOF\\n\"\n"
9176
9177 and generate_java_bindtests () =
9178   generate_header CStyle GPLv2;
9179
9180   pr "\
9181 import com.redhat.et.libguestfs.*;
9182
9183 public class Bindtests {
9184     public static void main (String[] argv)
9185     {
9186         try {
9187             GuestFS g = new GuestFS ();
9188 ";
9189
9190   let mkargs args =
9191     String.concat ", " (
9192       List.map (
9193         function
9194         | CallString s -> "\"" ^ s ^ "\""
9195         | CallOptString None -> "null"
9196         | CallOptString (Some s) -> sprintf "\"%s\"" s
9197         | CallStringList xs ->
9198             "new String[]{" ^
9199               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9200         | CallInt i -> string_of_int i
9201         | CallBool b -> string_of_bool b
9202       ) args
9203     )
9204   in
9205
9206   generate_lang_bindtests (
9207     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9208   );
9209
9210   pr "
9211             System.out.println (\"EOF\");
9212         }
9213         catch (Exception exn) {
9214             System.err.println (exn);
9215             System.exit (1);
9216         }
9217     }
9218 }
9219 "
9220
9221 and generate_haskell_bindtests () =
9222   generate_header HaskellStyle GPLv2;
9223
9224   pr "\
9225 module Bindtests where
9226 import qualified Guestfs
9227
9228 main = do
9229   g <- Guestfs.create
9230 ";
9231
9232   let mkargs args =
9233     String.concat " " (
9234       List.map (
9235         function
9236         | CallString s -> "\"" ^ s ^ "\""
9237         | CallOptString None -> "Nothing"
9238         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9239         | CallStringList xs ->
9240             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9241         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9242         | CallInt i -> string_of_int i
9243         | CallBool true -> "True"
9244         | CallBool false -> "False"
9245       ) args
9246     )
9247   in
9248
9249   generate_lang_bindtests (
9250     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9251   );
9252
9253   pr "  putStrLn \"EOF\"\n"
9254
9255 (* Language-independent bindings tests - we do it this way to
9256  * ensure there is parity in testing bindings across all languages.
9257  *)
9258 and generate_lang_bindtests call =
9259   call "test0" [CallString "abc"; CallOptString (Some "def");
9260                 CallStringList []; CallBool false;
9261                 CallInt 0; CallString "123"; CallString "456"];
9262   call "test0" [CallString "abc"; CallOptString None;
9263                 CallStringList []; CallBool false;
9264                 CallInt 0; CallString "123"; CallString "456"];
9265   call "test0" [CallString ""; CallOptString (Some "def");
9266                 CallStringList []; CallBool false;
9267                 CallInt 0; CallString "123"; CallString "456"];
9268   call "test0" [CallString ""; CallOptString (Some "");
9269                 CallStringList []; CallBool false;
9270                 CallInt 0; CallString "123"; CallString "456"];
9271   call "test0" [CallString "abc"; CallOptString (Some "def");
9272                 CallStringList ["1"]; CallBool false;
9273                 CallInt 0; CallString "123"; CallString "456"];
9274   call "test0" [CallString "abc"; CallOptString (Some "def");
9275                 CallStringList ["1"; "2"]; CallBool false;
9276                 CallInt 0; CallString "123"; CallString "456"];
9277   call "test0" [CallString "abc"; CallOptString (Some "def");
9278                 CallStringList ["1"]; CallBool true;
9279                 CallInt 0; CallString "123"; CallString "456"];
9280   call "test0" [CallString "abc"; CallOptString (Some "def");
9281                 CallStringList ["1"]; CallBool false;
9282                 CallInt (-1); CallString "123"; CallString "456"];
9283   call "test0" [CallString "abc"; CallOptString (Some "def");
9284                 CallStringList ["1"]; CallBool false;
9285                 CallInt (-2); CallString "123"; CallString "456"];
9286   call "test0" [CallString "abc"; CallOptString (Some "def");
9287                 CallStringList ["1"]; CallBool false;
9288                 CallInt 1; CallString "123"; CallString "456"];
9289   call "test0" [CallString "abc"; CallOptString (Some "def");
9290                 CallStringList ["1"]; CallBool false;
9291                 CallInt 2; CallString "123"; CallString "456"];
9292   call "test0" [CallString "abc"; CallOptString (Some "def");
9293                 CallStringList ["1"]; CallBool false;
9294                 CallInt 4095; CallString "123"; CallString "456"];
9295   call "test0" [CallString "abc"; CallOptString (Some "def");
9296                 CallStringList ["1"]; CallBool false;
9297                 CallInt 0; CallString ""; CallString ""]
9298
9299 (* XXX Add here tests of the return and error functions. *)
9300
9301 (* This is used to generate the src/MAX_PROC_NR file which
9302  * contains the maximum procedure number, a surrogate for the
9303  * ABI version number.  See src/Makefile.am for the details.
9304  *)
9305 and generate_max_proc_nr () =
9306   let proc_nrs = List.map (
9307     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9308   ) daemon_functions in
9309
9310   let max_proc_nr = List.fold_left max 0 proc_nrs in
9311
9312   pr "%d\n" max_proc_nr
9313
9314 let output_to filename =
9315   let filename_new = filename ^ ".new" in
9316   chan := open_out filename_new;
9317   let close () =
9318     close_out !chan;
9319     chan := stdout;
9320
9321     (* Is the new file different from the current file? *)
9322     if Sys.file_exists filename && files_equal filename filename_new then
9323       Unix.unlink filename_new          (* same, so skip it *)
9324     else (
9325       (* different, overwrite old one *)
9326       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9327       Unix.rename filename_new filename;
9328       Unix.chmod filename 0o444;
9329       printf "written %s\n%!" filename;
9330     )
9331   in
9332   close
9333
9334 (* Main program. *)
9335 let () =
9336   check_functions ();
9337
9338   if not (Sys.file_exists "HACKING") then (
9339     eprintf "\
9340 You are probably running this from the wrong directory.
9341 Run it from the top source directory using the command
9342   src/generator.ml
9343 ";
9344     exit 1
9345   );
9346
9347   let close = output_to "src/guestfs_protocol.x" in
9348   generate_xdr ();
9349   close ();
9350
9351   let close = output_to "src/guestfs-structs.h" in
9352   generate_structs_h ();
9353   close ();
9354
9355   let close = output_to "src/guestfs-actions.h" in
9356   generate_actions_h ();
9357   close ();
9358
9359   let close = output_to "src/guestfs-actions.c" in
9360   generate_client_actions ();
9361   close ();
9362
9363   let close = output_to "daemon/actions.h" in
9364   generate_daemon_actions_h ();
9365   close ();
9366
9367   let close = output_to "daemon/stubs.c" in
9368   generate_daemon_actions ();
9369   close ();
9370
9371   let close = output_to "daemon/names.c" in
9372   generate_daemon_names ();
9373   close ();
9374
9375   let close = output_to "capitests/tests.c" in
9376   generate_tests ();
9377   close ();
9378
9379   let close = output_to "src/guestfs-bindtests.c" in
9380   generate_bindtests ();
9381   close ();
9382
9383   let close = output_to "fish/cmds.c" in
9384   generate_fish_cmds ();
9385   close ();
9386
9387   let close = output_to "fish/completion.c" in
9388   generate_fish_completion ();
9389   close ();
9390
9391   let close = output_to "guestfs-structs.pod" in
9392   generate_structs_pod ();
9393   close ();
9394
9395   let close = output_to "guestfs-actions.pod" in
9396   generate_actions_pod ();
9397   close ();
9398
9399   let close = output_to "guestfish-actions.pod" in
9400   generate_fish_actions_pod ();
9401   close ();
9402
9403   let close = output_to "ocaml/guestfs.mli" in
9404   generate_ocaml_mli ();
9405   close ();
9406
9407   let close = output_to "ocaml/guestfs.ml" in
9408   generate_ocaml_ml ();
9409   close ();
9410
9411   let close = output_to "ocaml/guestfs_c_actions.c" in
9412   generate_ocaml_c ();
9413   close ();
9414
9415   let close = output_to "ocaml/bindtests.ml" in
9416   generate_ocaml_bindtests ();
9417   close ();
9418
9419   let close = output_to "perl/Guestfs.xs" in
9420   generate_perl_xs ();
9421   close ();
9422
9423   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9424   generate_perl_pm ();
9425   close ();
9426
9427   let close = output_to "perl/bindtests.pl" in
9428   generate_perl_bindtests ();
9429   close ();
9430
9431   let close = output_to "python/guestfs-py.c" in
9432   generate_python_c ();
9433   close ();
9434
9435   let close = output_to "python/guestfs.py" in
9436   generate_python_py ();
9437   close ();
9438
9439   let close = output_to "python/bindtests.py" in
9440   generate_python_bindtests ();
9441   close ();
9442
9443   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9444   generate_ruby_c ();
9445   close ();
9446
9447   let close = output_to "ruby/bindtests.rb" in
9448   generate_ruby_bindtests ();
9449   close ();
9450
9451   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9452   generate_java_java ();
9453   close ();
9454
9455   List.iter (
9456     fun (typ, jtyp) ->
9457       let cols = cols_of_struct typ in
9458       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9459       let close = output_to filename in
9460       generate_java_struct jtyp cols;
9461       close ();
9462   ) java_structs;
9463
9464   let close = output_to "java/Makefile.inc" in
9465   generate_java_makefile_inc ();
9466   close ();
9467
9468   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9469   generate_java_c ();
9470   close ();
9471
9472   let close = output_to "java/Bindtests.java" in
9473   generate_java_bindtests ();
9474   close ();
9475
9476   let close = output_to "haskell/Guestfs.hs" in
9477   generate_haskell_hs ();
9478   close ();
9479
9480   let close = output_to "haskell/Bindtests.hs" in
9481   generate_haskell_bindtests ();
9482   close ();
9483
9484   let close = output_to "src/MAX_PROC_NR" in
9485   generate_max_proc_nr ();
9486   close ();
9487
9488   (* Always generate this file last, and unconditionally.  It's used
9489    * by the Makefile to know when we must re-run the generator.
9490    *)
9491   let chan = open_out "src/stamp-generator" in
9492   fprintf chan "1\n";
9493   close_out chan