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