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