New API: case-sensitive-path to return case sensitive path on NTFS 3g fs
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145     (* These are treated as filenames (simple string parameters) in
146      * the C API and bindings.  But in the RPC protocol, we transfer
147      * the actual file content up to or down from the daemon.
148      * FileIn: local machine -> daemon (in request)
149      * FileOut: daemon -> local machine (in reply)
150      * In guestfish (only), the special name "-" means read from
151      * stdin or write to stdout.
152      *)
153   | FileIn of string
154   | FileOut of string
155 (* Not implemented:
156     (* Opaque buffer which can contain arbitrary 8 bit data.
157      * In the C API, this is expressed as <char *, int> pair.
158      * Most other languages have a string type which can contain
159      * ASCII NUL.  We use whatever type is appropriate for each
160      * language.
161      * Buffers are limited by the total message size.  To transfer
162      * large blocks of data, use FileIn/FileOut parameters instead.
163      * To return an arbitrary buffer, use RBufferOut.
164      *)
165   | BufferIn of string
166 *)
167
168 type flags =
169   | ProtocolLimitWarning  (* display warning about protocol size limits *)
170   | DangerWillRobinson    (* flags particularly dangerous commands *)
171   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
172   | FishAction of string  (* call this function in guestfish *)
173   | NotInFish             (* do not export via guestfish *)
174   | NotInDocs             (* do not add this function to documentation *)
175   | DeprecatedBy of string (* function is deprecated, use .. instead *)
176
177 (* You can supply zero or as many tests as you want per API call.
178  *
179  * Note that the test environment has 3 block devices, of size 500MB,
180  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181  * a fourth ISO block device with some known files on it (/dev/sdd).
182  *
183  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184  * Number of cylinders was 63 for IDE emulated disks with precisely
185  * the same size.  How exactly this is calculated is a mystery.
186  *
187  * The ISO block device (/dev/sdd) comes from images/test.iso.
188  *
189  * To be able to run the tests in a reasonable amount of time,
190  * the virtual machine and block devices are reused between tests.
191  * So don't try testing kill_subprocess :-x
192  *
193  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194  *
195  * Don't assume anything about the previous contents of the block
196  * devices.  Use 'Init*' to create some initial scenarios.
197  *
198  * You can add a prerequisite clause to any individual test.  This
199  * is a run-time check, which, if it fails, causes the test to be
200  * skipped.  Useful if testing a command which might not work on
201  * all variations of libguestfs builds.  A test that has prerequisite
202  * of 'Always' is run unconditionally.
203  *
204  * In addition, packagers can skip individual tests by setting the
205  * environment variables:     eg:
206  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
207  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
208  *)
209 type tests = (test_init * test_prereq * test) list
210 and test =
211     (* Run the command sequence and just expect nothing to fail. *)
212   | TestRun of seq
213
214     (* Run the command sequence and expect the output of the final
215      * command to be the string.
216      *)
217   | TestOutput of seq * string
218
219     (* Run the command sequence and expect the output of the final
220      * command to be the list of strings.
221      *)
222   | TestOutputList of seq * string list
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the list of block devices (could be either
226      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227      * character of each string).
228      *)
229   | TestOutputListOfDevices of seq * string list
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the integer.
233      *)
234   | TestOutputInt of seq * int
235
236     (* Run the command sequence and expect the output of the final
237      * command to be <op> <int>, eg. ">=", "1".
238      *)
239   | TestOutputIntOp of seq * string * int
240
241     (* Run the command sequence and expect the output of the final
242      * command to be a true value (!= 0 or != NULL).
243      *)
244   | TestOutputTrue of seq
245
246     (* Run the command sequence and expect the output of the final
247      * command to be a false value (== 0 or == NULL, but not an error).
248      *)
249   | TestOutputFalse of seq
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a list of the given length (but don't care about
253      * content).
254      *)
255   | TestOutputLength of seq * int
256
257     (* Run the command sequence and expect the output of the final
258      * command to be a buffer (RBufferOut), ie. string + size.
259      *)
260   | TestOutputBuffer of seq * string
261
262     (* Run the command sequence and expect the output of the final
263      * command to be a structure.
264      *)
265   | TestOutputStruct of seq * test_field_compare list
266
267     (* Run the command sequence and expect the final command (only)
268      * to fail.
269      *)
270   | TestLastFail of seq
271
272 and test_field_compare =
273   | CompareWithInt of string * int
274   | CompareWithIntOp of string * string * int
275   | CompareWithString of string * string
276   | CompareFieldsIntEq of string * string
277   | CompareFieldsStrEq of string * string
278
279 (* Test prerequisites. *)
280 and test_prereq =
281     (* Test always runs. *)
282   | Always
283
284     (* Test is currently disabled - eg. it fails, or it tests some
285      * unimplemented feature.
286      *)
287   | Disabled
288
289     (* 'string' is some C code (a function body) that should return
290      * true or false.  The test will run if the code returns true.
291      *)
292   | If of string
293
294     (* As for 'If' but the test runs _unless_ the code returns true. *)
295   | Unless of string
296
297 (* Some initial scenarios for testing. *)
298 and test_init =
299     (* Do nothing, block devices could contain random stuff including
300      * LVM PVs, and some filesystems might be mounted.  This is usually
301      * a bad idea.
302      *)
303   | InitNone
304
305     (* Block devices are empty and no filesystems are mounted. *)
306   | InitEmpty
307
308     (* /dev/sda contains a single partition /dev/sda1, with random
309      * content.  /dev/sdb and /dev/sdc may have random content.
310      * No LVM.
311      *)
312   | InitPartition
313
314     (* /dev/sda contains a single partition /dev/sda1, which is formatted
315      * as ext2, empty [except for lost+found] and mounted on /.
316      * /dev/sdb and /dev/sdc may have random content.
317      * No LVM.
318      *)
319   | InitBasicFS
320
321     (* /dev/sda:
322      *   /dev/sda1 (is a PV):
323      *     /dev/VG/LV (size 8MB):
324      *       formatted as ext2, empty [except for lost+found], mounted on /
325      * /dev/sdb and /dev/sdc may have random content.
326      *)
327   | InitBasicFSonLVM
328
329     (* /dev/sdd (the ISO, see images/ directory in source)
330      * is mounted on /
331      *)
332   | InitISOFS
333
334 (* Sequence of commands for testing. *)
335 and seq = cmd list
336 and cmd = string list
337
338 (* Note about long descriptions: When referring to another
339  * action, use the format C<guestfs_other> (ie. the full name of
340  * the C function).  This will be replaced as appropriate in other
341  * language bindings.
342  *
343  * Apart from that, long descriptions are just perldoc paragraphs.
344  *)
345
346 (* Generate a random UUID (used in tests). *)
347 let uuidgen () =
348   let chan = Unix.open_process_in "uuidgen" in
349   let uuid = input_line chan in
350   (match Unix.close_process_in chan with
351    | Unix.WEXITED 0 -> ()
352    | Unix.WEXITED _ ->
353        failwith "uuidgen: process exited with non-zero status"
354    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355        failwith "uuidgen: process signalled or stopped by signal"
356   );
357   uuid
358
359 (* These test functions are used in the language binding tests. *)
360
361 let test_all_args = [
362   String "str";
363   OptString "optstr";
364   StringList "strlist";
365   Bool "b";
366   Int "integer";
367   FileIn "filein";
368   FileOut "fileout";
369 ]
370
371 let test_all_rets = [
372   (* except for RErr, which is tested thoroughly elsewhere *)
373   "test0rint",         RInt "valout";
374   "test0rint64",       RInt64 "valout";
375   "test0rbool",        RBool "valout";
376   "test0rconststring", RConstString "valout";
377   "test0rconstoptstring", RConstOptString "valout";
378   "test0rstring",      RString "valout";
379   "test0rstringlist",  RStringList "valout";
380   "test0rstruct",      RStruct ("valout", "lvm_pv");
381   "test0rstructlist",  RStructList ("valout", "lvm_pv");
382   "test0rhashtable",   RHashtable "valout";
383 ]
384
385 let test_functions = [
386   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387    [],
388    "internal test function - do not use",
389    "\
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
393
394 It echos the contents of each parameter to stdout.
395
396 You probably don't want to call this function.");
397 ] @ List.flatten (
398   List.map (
399     fun (name, ret) ->
400       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401         [],
402         "internal test function - do not use",
403         "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 return type correctly.
407
408 It converts string C<val> to the return type.
409
410 You probably don't want to call this function.");
411        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412         [],
413         "internal test function - do not use",
414         "\
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
418
419 This function always returns an error.
420
421 You probably don't want to call this function.")]
422   ) test_all_rets
423 )
424
425 (* non_daemon_functions are any functions which don't get processed
426  * in the daemon, eg. functions for setting and getting local
427  * configuration values.
428  *)
429
430 let non_daemon_functions = test_functions @ [
431   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432    [],
433    "launch the qemu subprocess",
434    "\
435 Internally libguestfs is implemented by running a virtual machine
436 using L<qemu(1)>.
437
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
440
441   ("wait_ready", (RErr, []), -1, [NotInFish],
442    [],
443    "wait until the qemu subprocess launches (no op)",
444    "\
445 This function is a no op.
446
447 In versions of the API E<lt> 1.0.71 you had to call this function
448 just after calling C<guestfs_launch> to wait for the launch
449 to complete.  However this is no longer necessary because
450 C<guestfs_launch> now does the waiting.
451
452 If you see any calls to this function in code then you can just
453 remove them, unless you want to retain compatibility with older
454 versions of the API.");
455
456   ("kill_subprocess", (RErr, []), -1, [],
457    [],
458    "kill the qemu subprocess",
459    "\
460 This kills the qemu subprocess.  You should never need to call this.");
461
462   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
463    [],
464    "add an image to examine or modify",
465    "\
466 This function adds a virtual machine disk image C<filename> to the
467 guest.  The first time you call this function, the disk appears as IDE
468 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
469 so on.
470
471 You don't necessarily need to be root when using libguestfs.  However
472 you obviously do need sufficient permissions to access the filename
473 for whatever operations you want to perform (ie. read access if you
474 just want to read the image or write access if you want to modify the
475 image).
476
477 This is equivalent to the qemu parameter
478 C<-drive file=filename,cache=off,if=...>.
479 C<cache=off> is omitted in cases where it is not supported by
480 the underlying filesystem.
481
482 Note that this call checks for the existence of C<filename>.  This
483 stops you from specifying other types of drive which are supported
484 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
485 the general C<guestfs_config> call instead.");
486
487   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
488    [],
489    "add a CD-ROM disk image to examine",
490    "\
491 This function adds a virtual CD-ROM disk image to the guest.
492
493 This is equivalent to the qemu parameter C<-cdrom filename>.
494
495 Note that this call checks for the existence of C<filename>.  This
496 stops you from specifying other types of drive which are supported
497 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
498 the general C<guestfs_config> call instead.");
499
500   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
501    [],
502    "add a drive in snapshot mode (read-only)",
503    "\
504 This adds a drive in snapshot mode, making it effectively
505 read-only.
506
507 Note that writes to the device are allowed, and will be seen for
508 the duration of the guestfs handle, but they are written
509 to a temporary file which is discarded as soon as the guestfs
510 handle is closed.  We don't currently have any method to enable
511 changes to be committed, although qemu can support this.
512
513 This is equivalent to the qemu parameter
514 C<-drive file=filename,snapshot=on,if=...>.
515
516 Note that this call checks for the existence of C<filename>.  This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
519 the general C<guestfs_config> call instead.");
520
521   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
522    [],
523    "add qemu parameters",
524    "\
525 This can be used to add arbitrary qemu command line parameters
526 of the form C<-param value>.  Actually it's not quite arbitrary - we
527 prevent you from setting some parameters which would interfere with
528 parameters that we use.
529
530 The first character of C<param> string must be a C<-> (dash).
531
532 C<value> can be NULL.");
533
534   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
535    [],
536    "set the qemu binary",
537    "\
538 Set the qemu binary that we will use.
539
540 The default is chosen when the library was compiled by the
541 configure script.
542
543 You can also override this by setting the C<LIBGUESTFS_QEMU>
544 environment variable.
545
546 Setting C<qemu> to C<NULL> restores the default qemu binary.");
547
548   ("get_qemu", (RConstString "qemu", []), -1, [],
549    [InitNone, Always, TestRun (
550       [["get_qemu"]])],
551    "get the qemu binary",
552    "\
553 Return the current qemu binary.
554
555 This is always non-NULL.  If it wasn't set already, then this will
556 return the default qemu binary name.");
557
558   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
559    [],
560    "set the search path",
561    "\
562 Set the path that libguestfs searches for kernel and initrd.img.
563
564 The default is C<$libdir/guestfs> unless overridden by setting
565 C<LIBGUESTFS_PATH> environment variable.
566
567 Setting C<path> to C<NULL> restores the default path.");
568
569   ("get_path", (RConstString "path", []), -1, [],
570    [InitNone, Always, TestRun (
571       [["get_path"]])],
572    "get the search path",
573    "\
574 Return the current search path.
575
576 This is always non-NULL.  If it wasn't set already, then this will
577 return the default path.");
578
579   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
580    [],
581    "add options to kernel command line",
582    "\
583 This function is used to add additional options to the
584 guest kernel command line.
585
586 The default is C<NULL> unless overridden by setting
587 C<LIBGUESTFS_APPEND> environment variable.
588
589 Setting C<append> to C<NULL> means I<no> additional options
590 are passed (libguestfs always adds a few of its own).");
591
592   ("get_append", (RConstOptString "append", []), -1, [],
593    (* This cannot be tested with the current framework.  The
594     * function can return NULL in normal operations, which the
595     * test framework interprets as an error.
596     *)
597    [],
598    "get the additional kernel options",
599    "\
600 Return the additional kernel options which are added to the
601 guest kernel command line.
602
603 If C<NULL> then no options are added.");
604
605   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
606    [],
607    "set autosync mode",
608    "\
609 If C<autosync> is true, this enables autosync.  Libguestfs will make a
610 best effort attempt to run C<guestfs_umount_all> followed by
611 C<guestfs_sync> when the handle is closed
612 (also if the program exits without closing handles).
613
614 This is disabled by default (except in guestfish where it is
615 enabled by default).");
616
617   ("get_autosync", (RBool "autosync", []), -1, [],
618    [InitNone, Always, TestRun (
619       [["get_autosync"]])],
620    "get autosync mode",
621    "\
622 Get the autosync flag.");
623
624   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
625    [],
626    "set verbose mode",
627    "\
628 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
629
630 Verbose messages are disabled unless the environment variable
631 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
632
633   ("get_verbose", (RBool "verbose", []), -1, [],
634    [],
635    "get verbose mode",
636    "\
637 This returns the verbose messages flag.");
638
639   ("is_ready", (RBool "ready", []), -1, [],
640    [InitNone, Always, TestOutputTrue (
641       [["is_ready"]])],
642    "is ready to accept commands",
643    "\
644 This returns true iff this handle is ready to accept commands
645 (in the C<READY> state).
646
647 For more information on states, see L<guestfs(3)>.");
648
649   ("is_config", (RBool "config", []), -1, [],
650    [InitNone, Always, TestOutputFalse (
651       [["is_config"]])],
652    "is in configuration state",
653    "\
654 This returns true iff this handle is being configured
655 (in the C<CONFIG> state).
656
657 For more information on states, see L<guestfs(3)>.");
658
659   ("is_launching", (RBool "launching", []), -1, [],
660    [InitNone, Always, TestOutputFalse (
661       [["is_launching"]])],
662    "is launching subprocess",
663    "\
664 This returns true iff this handle is launching the subprocess
665 (in the C<LAUNCHING> state).
666
667 For more information on states, see L<guestfs(3)>.");
668
669   ("is_busy", (RBool "busy", []), -1, [],
670    [InitNone, Always, TestOutputFalse (
671       [["is_busy"]])],
672    "is busy processing a command",
673    "\
674 This returns true iff this handle is busy processing a command
675 (in the C<BUSY> state).
676
677 For more information on states, see L<guestfs(3)>.");
678
679   ("get_state", (RInt "state", []), -1, [],
680    [],
681    "get the current state",
682    "\
683 This returns the current state as an opaque integer.  This is
684 only useful for printing debug and internal error messages.
685
686 For more information on states, see L<guestfs(3)>.");
687
688   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
689    [InitNone, Always, TestOutputInt (
690       [["set_memsize"; "500"];
691        ["get_memsize"]], 500)],
692    "set memory allocated to the qemu subprocess",
693    "\
694 This sets the memory size in megabytes allocated to the
695 qemu subprocess.  This only has any effect if called before
696 C<guestfs_launch>.
697
698 You can also change this by setting the environment
699 variable C<LIBGUESTFS_MEMSIZE> before the handle is
700 created.
701
702 For more information on the architecture of libguestfs,
703 see L<guestfs(3)>.");
704
705   ("get_memsize", (RInt "memsize", []), -1, [],
706    [InitNone, Always, TestOutputIntOp (
707       [["get_memsize"]], ">=", 256)],
708    "get memory allocated to the qemu subprocess",
709    "\
710 This gets the memory size in megabytes allocated to the
711 qemu subprocess.
712
713 If C<guestfs_set_memsize> was not called
714 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
715 then this returns the compiled-in default value for memsize.
716
717 For more information on the architecture of libguestfs,
718 see L<guestfs(3)>.");
719
720   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
721    [InitNone, Always, TestOutputIntOp (
722       [["get_pid"]], ">=", 1)],
723    "get PID of qemu subprocess",
724    "\
725 Return the process ID of the qemu subprocess.  If there is no
726 qemu subprocess, then this will return an error.
727
728 This is an internal call used for debugging and testing.");
729
730   ("version", (RStruct ("version", "version"), []), -1, [],
731    [InitNone, Always, TestOutputStruct (
732       [["version"]], [CompareWithInt ("major", 1)])],
733    "get the library version number",
734    "\
735 Return the libguestfs version number that the program is linked
736 against.
737
738 Note that because of dynamic linking this is not necessarily
739 the version of libguestfs that you compiled against.  You can
740 compile the program, and then at runtime dynamically link
741 against a completely different C<libguestfs.so> library.
742
743 This call was added in version C<1.0.58>.  In previous
744 versions of libguestfs there was no way to get the version
745 number.  From C code you can use ELF weak linking tricks to find out if
746 this symbol exists (if it doesn't, then it's an earlier version).
747
748 The call returns a structure with four elements.  The first
749 three (C<major>, C<minor> and C<release>) are numbers and
750 correspond to the usual version triplet.  The fourth element
751 (C<extra>) is a string and is normally empty, but may be
752 used for distro-specific information.
753
754 To construct the original version string:
755 C<$major.$minor.$release$extra>
756
757 I<Note:> Don't use this call to test for availability
758 of features.  Distro backports makes this unreliable.");
759
760   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
761    [InitNone, Always, TestOutputTrue (
762       [["set_selinux"; "true"];
763        ["get_selinux"]])],
764    "set SELinux enabled or disabled at appliance boot",
765    "\
766 This sets the selinux flag that is passed to the appliance
767 at boot time.  The default is C<selinux=0> (disabled).
768
769 Note that if SELinux is enabled, it is always in
770 Permissive mode (C<enforcing=0>).
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_selinux", (RBool "selinux", []), -1, [],
776    [],
777    "get SELinux enabled flag",
778    "\
779 This returns the current setting of the selinux flag which
780 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
781
782 For more information on the architecture of libguestfs,
783 see L<guestfs(3)>.");
784
785   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
786    [InitNone, Always, TestOutputFalse (
787       [["set_trace"; "false"];
788        ["get_trace"]])],
789    "enable or disable command traces",
790    "\
791 If the command trace flag is set to 1, then commands are
792 printed on stdout before they are executed in a format
793 which is very similar to the one used by guestfish.  In
794 other words, you can run a program with this enabled, and
795 you will get out a script which you can feed to guestfish
796 to perform the same set of actions.
797
798 If you want to trace C API calls into libguestfs (and
799 other libraries) then possibly a better way is to use
800 the external ltrace(1) command.
801
802 Command traces are disabled unless the environment variable
803 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
804
805   ("get_trace", (RBool "trace", []), -1, [],
806    [],
807    "get command trace enabled flag",
808    "\
809 Return the command trace flag.");
810
811   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
812    [InitNone, Always, TestOutputFalse (
813       [["set_direct"; "false"];
814        ["get_direct"]])],
815    "enable or disable direct appliance mode",
816    "\
817 If the direct appliance mode flag is enabled, then stdin and
818 stdout are passed directly through to the appliance once it
819 is launched.
820
821 One consequence of this is that log messages aren't caught
822 by the library and handled by C<guestfs_set_log_message_callback>,
823 but go straight to stdout.
824
825 You probably don't want to use this unless you know what you
826 are doing.
827
828 The default is disabled.");
829
830   ("get_direct", (RBool "direct", []), -1, [],
831    [],
832    "get direct appliance mode flag",
833    "\
834 Return the direct appliance mode flag.");
835
836 ]
837
838 (* daemon_functions are any functions which cause some action
839  * to take place in the daemon.
840  *)
841
842 let daemon_functions = [
843   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
844    [InitEmpty, Always, TestOutput (
845       [["sfdiskM"; "/dev/sda"; ","];
846        ["mkfs"; "ext2"; "/dev/sda1"];
847        ["mount"; "/dev/sda1"; "/"];
848        ["write_file"; "/new"; "new file contents"; "0"];
849        ["cat"; "/new"]], "new file contents")],
850    "mount a guest disk at a position in the filesystem",
851    "\
852 Mount a guest disk at a position in the filesystem.  Block devices
853 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
854 the guest.  If those block devices contain partitions, they will have
855 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
856 names can be used.
857
858 The rules are the same as for L<mount(2)>:  A filesystem must
859 first be mounted on C</> before others can be mounted.  Other
860 filesystems can only be mounted on directories which already
861 exist.
862
863 The mounted filesystem is writable, if we have sufficient permissions
864 on the underlying device.
865
866 The filesystem options C<sync> and C<noatime> are set with this
867 call, in order to improve reliability.");
868
869   ("sync", (RErr, []), 2, [],
870    [ InitEmpty, Always, TestRun [["sync"]]],
871    "sync disks, writes are flushed through to the disk image",
872    "\
873 This syncs the disk, so that any writes are flushed through to the
874 underlying disk image.
875
876 You should always call this if you have modified a disk image, before
877 closing the handle.");
878
879   ("touch", (RErr, [Pathname "path"]), 3, [],
880    [InitBasicFS, Always, TestOutputTrue (
881       [["touch"; "/new"];
882        ["exists"; "/new"]])],
883    "update file timestamps or create a new file",
884    "\
885 Touch acts like the L<touch(1)> command.  It can be used to
886 update the timestamps on a file, or, if the file does not exist,
887 to create a new zero-length file.");
888
889   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
890    [InitISOFS, Always, TestOutput (
891       [["cat"; "/known-2"]], "abcdef\n")],
892    "list the contents of a file",
893    "\
894 Return the contents of the file named C<path>.
895
896 Note that this function cannot correctly handle binary files
897 (specifically, files containing C<\\0> character which is treated
898 as end of string).  For those you need to use the C<guestfs_read_file>
899 or C<guestfs_download> functions which have a more complex interface.");
900
901   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
902    [], (* XXX Tricky to test because it depends on the exact format
903         * of the 'ls -l' command, which changes between F10 and F11.
904         *)
905    "list the files in a directory (long format)",
906    "\
907 List the files in C<directory> (relative to the root directory,
908 there is no cwd) in the format of 'ls -la'.
909
910 This command is mostly useful for interactive sessions.  It
911 is I<not> intended that you try to parse the output string.");
912
913   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
914    [InitBasicFS, Always, TestOutputList (
915       [["touch"; "/new"];
916        ["touch"; "/newer"];
917        ["touch"; "/newest"];
918        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
919    "list the files in a directory",
920    "\
921 List the files in C<directory> (relative to the root directory,
922 there is no cwd).  The '.' and '..' entries are not returned, but
923 hidden files are shown.
924
925 This command is mostly useful for interactive sessions.  Programs
926 should probably use C<guestfs_readdir> instead.");
927
928   ("list_devices", (RStringList "devices", []), 7, [],
929    [InitEmpty, Always, TestOutputListOfDevices (
930       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
931    "list the block devices",
932    "\
933 List all the block devices.
934
935 The full block device names are returned, eg. C</dev/sda>");
936
937   ("list_partitions", (RStringList "partitions", []), 8, [],
938    [InitBasicFS, Always, TestOutputListOfDevices (
939       [["list_partitions"]], ["/dev/sda1"]);
940     InitEmpty, Always, TestOutputListOfDevices (
941       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
942        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
943    "list the partitions",
944    "\
945 List all the partitions detected on all block devices.
946
947 The full partition device names are returned, eg. C</dev/sda1>
948
949 This does not return logical volumes.  For that you will need to
950 call C<guestfs_lvs>.");
951
952   ("pvs", (RStringList "physvols", []), 9, [],
953    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
954       [["pvs"]], ["/dev/sda1"]);
955     InitEmpty, Always, TestOutputListOfDevices (
956       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
957        ["pvcreate"; "/dev/sda1"];
958        ["pvcreate"; "/dev/sda2"];
959        ["pvcreate"; "/dev/sda3"];
960        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
961    "list the LVM physical volumes (PVs)",
962    "\
963 List all the physical volumes detected.  This is the equivalent
964 of the L<pvs(8)> command.
965
966 This returns a list of just the device names that contain
967 PVs (eg. C</dev/sda2>).
968
969 See also C<guestfs_pvs_full>.");
970
971   ("vgs", (RStringList "volgroups", []), 10, [],
972    [InitBasicFSonLVM, Always, TestOutputList (
973       [["vgs"]], ["VG"]);
974     InitEmpty, Always, TestOutputList (
975       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
976        ["pvcreate"; "/dev/sda1"];
977        ["pvcreate"; "/dev/sda2"];
978        ["pvcreate"; "/dev/sda3"];
979        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
980        ["vgcreate"; "VG2"; "/dev/sda3"];
981        ["vgs"]], ["VG1"; "VG2"])],
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.
986
987 This returns a list of just the volume group names that were
988 detected (eg. C<VolGroup00>).
989
990 See also C<guestfs_vgs_full>.");
991
992   ("lvs", (RStringList "logvols", []), 11, [],
993    [InitBasicFSonLVM, Always, TestOutputList (
994       [["lvs"]], ["/dev/VG/LV"]);
995     InitEmpty, Always, TestOutputList (
996       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
997        ["pvcreate"; "/dev/sda1"];
998        ["pvcreate"; "/dev/sda2"];
999        ["pvcreate"; "/dev/sda3"];
1000        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1001        ["vgcreate"; "VG2"; "/dev/sda3"];
1002        ["lvcreate"; "LV1"; "VG1"; "50"];
1003        ["lvcreate"; "LV2"; "VG1"; "50"];
1004        ["lvcreate"; "LV3"; "VG2"; "50"];
1005        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1006    "list the LVM logical volumes (LVs)",
1007    "\
1008 List all the logical volumes detected.  This is the equivalent
1009 of the L<lvs(8)> command.
1010
1011 This returns a list of the logical volume device names
1012 (eg. C</dev/VolGroup00/LogVol00>).
1013
1014 See also C<guestfs_lvs_full>.");
1015
1016   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1017    [], (* XXX how to test? *)
1018    "list the LVM physical volumes (PVs)",
1019    "\
1020 List all the physical volumes detected.  This is the equivalent
1021 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1022
1023   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1024    [], (* XXX how to test? *)
1025    "list the LVM volume groups (VGs)",
1026    "\
1027 List all the volumes groups detected.  This is the equivalent
1028 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1029
1030   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1031    [], (* XXX how to test? *)
1032    "list the LVM logical volumes (LVs)",
1033    "\
1034 List all the logical volumes detected.  This is the equivalent
1035 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1036
1037   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1038    [InitISOFS, Always, TestOutputList (
1039       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1040     InitISOFS, Always, TestOutputList (
1041       [["read_lines"; "/empty"]], [])],
1042    "read file as lines",
1043    "\
1044 Return the contents of the file named C<path>.
1045
1046 The file contents are returned as a list of lines.  Trailing
1047 C<LF> and C<CRLF> character sequences are I<not> returned.
1048
1049 Note that this function cannot correctly handle binary files
1050 (specifically, files containing C<\\0> character which is treated
1051 as end of line).  For those you need to use the C<guestfs_read_file>
1052 function which has a more complex interface.");
1053
1054   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1055    [], (* XXX Augeas code needs tests. *)
1056    "create a new Augeas handle",
1057    "\
1058 Create a new Augeas handle for editing configuration files.
1059 If there was any previous Augeas handle associated with this
1060 guestfs session, then it is closed.
1061
1062 You must call this before using any other C<guestfs_aug_*>
1063 commands.
1064
1065 C<root> is the filesystem root.  C<root> must not be NULL,
1066 use C</> instead.
1067
1068 The flags are the same as the flags defined in
1069 E<lt>augeas.hE<gt>, the logical I<or> of the following
1070 integers:
1071
1072 =over 4
1073
1074 =item C<AUG_SAVE_BACKUP> = 1
1075
1076 Keep the original file with a C<.augsave> extension.
1077
1078 =item C<AUG_SAVE_NEWFILE> = 2
1079
1080 Save changes into a file with extension C<.augnew>, and
1081 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1082
1083 =item C<AUG_TYPE_CHECK> = 4
1084
1085 Typecheck lenses (can be expensive).
1086
1087 =item C<AUG_NO_STDINC> = 8
1088
1089 Do not use standard load path for modules.
1090
1091 =item C<AUG_SAVE_NOOP> = 16
1092
1093 Make save a no-op, just record what would have been changed.
1094
1095 =item C<AUG_NO_LOAD> = 32
1096
1097 Do not load the tree in C<guestfs_aug_init>.
1098
1099 =back
1100
1101 To close the handle, you can call C<guestfs_aug_close>.
1102
1103 To find out more about Augeas, see L<http://augeas.net/>.");
1104
1105   ("aug_close", (RErr, []), 26, [],
1106    [], (* XXX Augeas code needs tests. *)
1107    "close the current Augeas handle",
1108    "\
1109 Close the current Augeas handle and free up any resources
1110 used by it.  After calling this, you have to call
1111 C<guestfs_aug_init> again before you can use any other
1112 Augeas functions.");
1113
1114   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1115    [], (* XXX Augeas code needs tests. *)
1116    "define an Augeas variable",
1117    "\
1118 Defines an Augeas variable C<name> whose value is the result
1119 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1120 undefined.
1121
1122 On success this returns the number of nodes in C<expr>, or
1123 C<0> if C<expr> evaluates to something which is not a nodeset.");
1124
1125   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1126    [], (* XXX Augeas code needs tests. *)
1127    "define an Augeas node",
1128    "\
1129 Defines a variable C<name> whose value is the result of
1130 evaluating C<expr>.
1131
1132 If C<expr> evaluates to an empty nodeset, a node is created,
1133 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1134 C<name> will be the nodeset containing that single node.
1135
1136 On success this returns a pair containing the
1137 number of nodes in the nodeset, and a boolean flag
1138 if a node was created.");
1139
1140   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1141    [], (* XXX Augeas code needs tests. *)
1142    "look up the value of an Augeas path",
1143    "\
1144 Look up the value associated with C<path>.  If C<path>
1145 matches exactly one node, the C<value> is returned.");
1146
1147   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1148    [], (* XXX Augeas code needs tests. *)
1149    "set Augeas path to value",
1150    "\
1151 Set the value associated with C<path> to C<value>.");
1152
1153   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1154    [], (* XXX Augeas code needs tests. *)
1155    "insert a sibling Augeas node",
1156    "\
1157 Create a new sibling C<label> for C<path>, inserting it into
1158 the tree before or after C<path> (depending on the boolean
1159 flag C<before>).
1160
1161 C<path> must match exactly one existing node in the tree, and
1162 C<label> must be a label, ie. not contain C</>, C<*> or end
1163 with a bracketed index C<[N]>.");
1164
1165   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1166    [], (* XXX Augeas code needs tests. *)
1167    "remove an Augeas path",
1168    "\
1169 Remove C<path> and all of its children.
1170
1171 On success this returns the number of entries which were removed.");
1172
1173   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1174    [], (* XXX Augeas code needs tests. *)
1175    "move Augeas node",
1176    "\
1177 Move the node C<src> to C<dest>.  C<src> must match exactly
1178 one node.  C<dest> is overwritten if it exists.");
1179
1180   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1181    [], (* XXX Augeas code needs tests. *)
1182    "return Augeas nodes which match augpath",
1183    "\
1184 Returns a list of paths which match the path expression C<path>.
1185 The returned paths are sufficiently qualified so that they match
1186 exactly one node in the current tree.");
1187
1188   ("aug_save", (RErr, []), 25, [],
1189    [], (* XXX Augeas code needs tests. *)
1190    "write all pending Augeas changes to disk",
1191    "\
1192 This writes all pending changes to disk.
1193
1194 The flags which were passed to C<guestfs_aug_init> affect exactly
1195 how files are saved.");
1196
1197   ("aug_load", (RErr, []), 27, [],
1198    [], (* XXX Augeas code needs tests. *)
1199    "load files into the tree",
1200    "\
1201 Load files into the tree.
1202
1203 See C<aug_load> in the Augeas documentation for the full gory
1204 details.");
1205
1206   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1207    [], (* XXX Augeas code needs tests. *)
1208    "list Augeas nodes under augpath",
1209    "\
1210 This is just a shortcut for listing C<guestfs_aug_match>
1211 C<path/*> and sorting the resulting nodes into alphabetical order.");
1212
1213   ("rm", (RErr, [Pathname "path"]), 29, [],
1214    [InitBasicFS, Always, TestRun
1215       [["touch"; "/new"];
1216        ["rm"; "/new"]];
1217     InitBasicFS, Always, TestLastFail
1218       [["rm"; "/new"]];
1219     InitBasicFS, Always, TestLastFail
1220       [["mkdir"; "/new"];
1221        ["rm"; "/new"]]],
1222    "remove a file",
1223    "\
1224 Remove the single file C<path>.");
1225
1226   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1227    [InitBasicFS, Always, TestRun
1228       [["mkdir"; "/new"];
1229        ["rmdir"; "/new"]];
1230     InitBasicFS, Always, TestLastFail
1231       [["rmdir"; "/new"]];
1232     InitBasicFS, Always, TestLastFail
1233       [["touch"; "/new"];
1234        ["rmdir"; "/new"]]],
1235    "remove a directory",
1236    "\
1237 Remove the single directory C<path>.");
1238
1239   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1240    [InitBasicFS, Always, TestOutputFalse
1241       [["mkdir"; "/new"];
1242        ["mkdir"; "/new/foo"];
1243        ["touch"; "/new/foo/bar"];
1244        ["rm_rf"; "/new"];
1245        ["exists"; "/new"]]],
1246    "remove a file or directory recursively",
1247    "\
1248 Remove the file or directory C<path>, recursively removing the
1249 contents if its a directory.  This is like the C<rm -rf> shell
1250 command.");
1251
1252   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1253    [InitBasicFS, Always, TestOutputTrue
1254       [["mkdir"; "/new"];
1255        ["is_dir"; "/new"]];
1256     InitBasicFS, Always, TestLastFail
1257       [["mkdir"; "/new/foo/bar"]]],
1258    "create a directory",
1259    "\
1260 Create a directory named C<path>.");
1261
1262   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1263    [InitBasicFS, Always, TestOutputTrue
1264       [["mkdir_p"; "/new/foo/bar"];
1265        ["is_dir"; "/new/foo/bar"]];
1266     InitBasicFS, Always, TestOutputTrue
1267       [["mkdir_p"; "/new/foo/bar"];
1268        ["is_dir"; "/new/foo"]];
1269     InitBasicFS, Always, TestOutputTrue
1270       [["mkdir_p"; "/new/foo/bar"];
1271        ["is_dir"; "/new"]];
1272     (* Regression tests for RHBZ#503133: *)
1273     InitBasicFS, Always, TestRun
1274       [["mkdir"; "/new"];
1275        ["mkdir_p"; "/new"]];
1276     InitBasicFS, Always, TestLastFail
1277       [["touch"; "/new"];
1278        ["mkdir_p"; "/new"]]],
1279    "create a directory and parents",
1280    "\
1281 Create a directory named C<path>, creating any parent directories
1282 as necessary.  This is like the C<mkdir -p> shell command.");
1283
1284   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1285    [], (* XXX Need stat command to test *)
1286    "change file mode",
1287    "\
1288 Change the mode (permissions) of C<path> to C<mode>.  Only
1289 numeric modes are supported.");
1290
1291   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1292    [], (* XXX Need stat command to test *)
1293    "change file owner and group",
1294    "\
1295 Change the file owner to C<owner> and group to C<group>.
1296
1297 Only numeric uid and gid are supported.  If you want to use
1298 names, you will need to locate and parse the password file
1299 yourself (Augeas support makes this relatively easy).");
1300
1301   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1302    [InitISOFS, Always, TestOutputTrue (
1303       [["exists"; "/empty"]]);
1304     InitISOFS, Always, TestOutputTrue (
1305       [["exists"; "/directory"]])],
1306    "test if file or directory exists",
1307    "\
1308 This returns C<true> if and only if there is a file, directory
1309 (or anything) with the given C<path> name.
1310
1311 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1312
1313   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1314    [InitISOFS, Always, TestOutputTrue (
1315       [["is_file"; "/known-1"]]);
1316     InitISOFS, Always, TestOutputFalse (
1317       [["is_file"; "/directory"]])],
1318    "test if file exists",
1319    "\
1320 This returns C<true> if and only if there is a file
1321 with the given C<path> name.  Note that it returns false for
1322 other objects like directories.
1323
1324 See also C<guestfs_stat>.");
1325
1326   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1327    [InitISOFS, Always, TestOutputFalse (
1328       [["is_dir"; "/known-3"]]);
1329     InitISOFS, Always, TestOutputTrue (
1330       [["is_dir"; "/directory"]])],
1331    "test if file exists",
1332    "\
1333 This returns C<true> if and only if there is a directory
1334 with the given C<path> name.  Note that it returns false for
1335 other objects like files.
1336
1337 See also C<guestfs_stat>.");
1338
1339   ("pvcreate", (RErr, [Device "device"]), 39, [],
1340    [InitEmpty, Always, TestOutputListOfDevices (
1341       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1342        ["pvcreate"; "/dev/sda1"];
1343        ["pvcreate"; "/dev/sda2"];
1344        ["pvcreate"; "/dev/sda3"];
1345        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1346    "create an LVM physical volume",
1347    "\
1348 This creates an LVM physical volume on the named C<device>,
1349 where C<device> should usually be a partition name such
1350 as C</dev/sda1>.");
1351
1352   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1353    [InitEmpty, Always, TestOutputList (
1354       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1355        ["pvcreate"; "/dev/sda1"];
1356        ["pvcreate"; "/dev/sda2"];
1357        ["pvcreate"; "/dev/sda3"];
1358        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1359        ["vgcreate"; "VG2"; "/dev/sda3"];
1360        ["vgs"]], ["VG1"; "VG2"])],
1361    "create an LVM volume group",
1362    "\
1363 This creates an LVM volume group called C<volgroup>
1364 from the non-empty list of physical volumes C<physvols>.");
1365
1366   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1367    [InitEmpty, Always, TestOutputList (
1368       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1369        ["pvcreate"; "/dev/sda1"];
1370        ["pvcreate"; "/dev/sda2"];
1371        ["pvcreate"; "/dev/sda3"];
1372        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1373        ["vgcreate"; "VG2"; "/dev/sda3"];
1374        ["lvcreate"; "LV1"; "VG1"; "50"];
1375        ["lvcreate"; "LV2"; "VG1"; "50"];
1376        ["lvcreate"; "LV3"; "VG2"; "50"];
1377        ["lvcreate"; "LV4"; "VG2"; "50"];
1378        ["lvcreate"; "LV5"; "VG2"; "50"];
1379        ["lvs"]],
1380       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1381        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1382    "create an LVM volume group",
1383    "\
1384 This creates an LVM volume group called C<logvol>
1385 on the volume group C<volgroup>, with C<size> megabytes.");
1386
1387   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1388    [InitEmpty, Always, TestOutput (
1389       [["sfdiskM"; "/dev/sda"; ","];
1390        ["mkfs"; "ext2"; "/dev/sda1"];
1391        ["mount"; "/dev/sda1"; "/"];
1392        ["write_file"; "/new"; "new file contents"; "0"];
1393        ["cat"; "/new"]], "new file contents")],
1394    "make a filesystem",
1395    "\
1396 This creates a filesystem on C<device> (usually a partition
1397 or LVM logical volume).  The filesystem type is C<fstype>, for
1398 example C<ext3>.");
1399
1400   ("sfdisk", (RErr, [Device "device";
1401                      Int "cyls"; Int "heads"; Int "sectors";
1402                      StringList "lines"]), 43, [DangerWillRobinson],
1403    [],
1404    "create partitions on a block device",
1405    "\
1406 This is a direct interface to the L<sfdisk(8)> program for creating
1407 partitions on block devices.
1408
1409 C<device> should be a block device, for example C</dev/sda>.
1410
1411 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1412 and sectors on the device, which are passed directly to sfdisk as
1413 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1414 of these, then the corresponding parameter is omitted.  Usually for
1415 'large' disks, you can just pass C<0> for these, but for small
1416 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1417 out the right geometry and you will need to tell it.
1418
1419 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1420 information refer to the L<sfdisk(8)> manpage.
1421
1422 To create a single partition occupying the whole disk, you would
1423 pass C<lines> as a single element list, when the single element being
1424 the string C<,> (comma).
1425
1426 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1427
1428   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1429    [InitBasicFS, Always, TestOutput (
1430       [["write_file"; "/new"; "new file contents"; "0"];
1431        ["cat"; "/new"]], "new file contents");
1432     InitBasicFS, Always, TestOutput (
1433       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1434        ["cat"; "/new"]], "\nnew file contents\n");
1435     InitBasicFS, Always, TestOutput (
1436       [["write_file"; "/new"; "\n\n"; "0"];
1437        ["cat"; "/new"]], "\n\n");
1438     InitBasicFS, Always, TestOutput (
1439       [["write_file"; "/new"; ""; "0"];
1440        ["cat"; "/new"]], "");
1441     InitBasicFS, Always, TestOutput (
1442       [["write_file"; "/new"; "\n\n\n"; "0"];
1443        ["cat"; "/new"]], "\n\n\n");
1444     InitBasicFS, Always, TestOutput (
1445       [["write_file"; "/new"; "\n"; "0"];
1446        ["cat"; "/new"]], "\n")],
1447    "create a file",
1448    "\
1449 This call creates a file called C<path>.  The contents of the
1450 file is the string C<content> (which can contain any 8 bit data),
1451 with length C<size>.
1452
1453 As a special case, if C<size> is C<0>
1454 then the length is calculated using C<strlen> (so in this case
1455 the content cannot contain embedded ASCII NULs).
1456
1457 I<NB.> Owing to a bug, writing content containing ASCII NUL
1458 characters does I<not> work, even if the length is specified.
1459 We hope to resolve this bug in a future version.  In the meantime
1460 use C<guestfs_upload>.");
1461
1462   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1463    [InitEmpty, Always, TestOutputListOfDevices (
1464       [["sfdiskM"; "/dev/sda"; ","];
1465        ["mkfs"; "ext2"; "/dev/sda1"];
1466        ["mount"; "/dev/sda1"; "/"];
1467        ["mounts"]], ["/dev/sda1"]);
1468     InitEmpty, Always, TestOutputList (
1469       [["sfdiskM"; "/dev/sda"; ","];
1470        ["mkfs"; "ext2"; "/dev/sda1"];
1471        ["mount"; "/dev/sda1"; "/"];
1472        ["umount"; "/"];
1473        ["mounts"]], [])],
1474    "unmount a filesystem",
1475    "\
1476 This unmounts the given filesystem.  The filesystem may be
1477 specified either by its mountpoint (path) or the device which
1478 contains the filesystem.");
1479
1480   ("mounts", (RStringList "devices", []), 46, [],
1481    [InitBasicFS, Always, TestOutputListOfDevices (
1482       [["mounts"]], ["/dev/sda1"])],
1483    "show mounted filesystems",
1484    "\
1485 This returns the list of currently mounted filesystems.  It returns
1486 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1487
1488 Some internal mounts are not shown.
1489
1490 See also: C<guestfs_mountpoints>");
1491
1492   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1493    [InitBasicFS, Always, TestOutputList (
1494       [["umount_all"];
1495        ["mounts"]], []);
1496     (* check that umount_all can unmount nested mounts correctly: *)
1497     InitEmpty, Always, TestOutputList (
1498       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1499        ["mkfs"; "ext2"; "/dev/sda1"];
1500        ["mkfs"; "ext2"; "/dev/sda2"];
1501        ["mkfs"; "ext2"; "/dev/sda3"];
1502        ["mount"; "/dev/sda1"; "/"];
1503        ["mkdir"; "/mp1"];
1504        ["mount"; "/dev/sda2"; "/mp1"];
1505        ["mkdir"; "/mp1/mp2"];
1506        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1507        ["mkdir"; "/mp1/mp2/mp3"];
1508        ["umount_all"];
1509        ["mounts"]], [])],
1510    "unmount all filesystems",
1511    "\
1512 This unmounts all mounted filesystems.
1513
1514 Some internal mounts are not unmounted by this call.");
1515
1516   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1517    [],
1518    "remove all LVM LVs, VGs and PVs",
1519    "\
1520 This command removes all LVM logical volumes, volume groups
1521 and physical volumes.");
1522
1523   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1524    [InitISOFS, Always, TestOutput (
1525       [["file"; "/empty"]], "empty");
1526     InitISOFS, Always, TestOutput (
1527       [["file"; "/known-1"]], "ASCII text");
1528     InitISOFS, Always, TestLastFail (
1529       [["file"; "/notexists"]])],
1530    "determine file type",
1531    "\
1532 This call uses the standard L<file(1)> command to determine
1533 the type or contents of the file.  This also works on devices,
1534 for example to find out whether a partition contains a filesystem.
1535
1536 This call will also transparently look inside various types
1537 of compressed file.
1538
1539 The exact command which runs is C<file -zbsL path>.  Note in
1540 particular that the filename is not prepended to the output
1541 (the C<-b> option).");
1542
1543   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1544    [InitBasicFS, Always, TestOutput (
1545       [["upload"; "test-command"; "/test-command"];
1546        ["chmod"; "0o755"; "/test-command"];
1547        ["command"; "/test-command 1"]], "Result1");
1548     InitBasicFS, Always, TestOutput (
1549       [["upload"; "test-command"; "/test-command"];
1550        ["chmod"; "0o755"; "/test-command"];
1551        ["command"; "/test-command 2"]], "Result2\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["upload"; "test-command"; "/test-command"];
1554        ["chmod"; "0o755"; "/test-command"];
1555        ["command"; "/test-command 3"]], "\nResult3");
1556     InitBasicFS, Always, TestOutput (
1557       [["upload"; "test-command"; "/test-command"];
1558        ["chmod"; "0o755"; "/test-command"];
1559        ["command"; "/test-command 4"]], "\nResult4\n");
1560     InitBasicFS, Always, TestOutput (
1561       [["upload"; "test-command"; "/test-command"];
1562        ["chmod"; "0o755"; "/test-command"];
1563        ["command"; "/test-command 5"]], "\nResult5\n\n");
1564     InitBasicFS, Always, TestOutput (
1565       [["upload"; "test-command"; "/test-command"];
1566        ["chmod"; "0o755"; "/test-command"];
1567        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1568     InitBasicFS, Always, TestOutput (
1569       [["upload"; "test-command"; "/test-command"];
1570        ["chmod"; "0o755"; "/test-command"];
1571        ["command"; "/test-command 7"]], "");
1572     InitBasicFS, Always, TestOutput (
1573       [["upload"; "test-command"; "/test-command"];
1574        ["chmod"; "0o755"; "/test-command"];
1575        ["command"; "/test-command 8"]], "\n");
1576     InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 9"]], "\n\n");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1588     InitBasicFS, Always, TestLastFail (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command"]])],
1592    "run a command from the guest filesystem",
1593    "\
1594 This call runs a command from the guest filesystem.  The
1595 filesystem must be mounted, and must contain a compatible
1596 operating system (ie. something Linux, with the same
1597 or compatible processor architecture).
1598
1599 The single parameter is an argv-style list of arguments.
1600 The first element is the name of the program to run.
1601 Subsequent elements are parameters.  The list must be
1602 non-empty (ie. must contain a program name).  Note that
1603 the command runs directly, and is I<not> invoked via
1604 the shell (see C<guestfs_sh>).
1605
1606 The return value is anything printed to I<stdout> by
1607 the command.
1608
1609 If the command returns a non-zero exit status, then
1610 this function returns an error message.  The error message
1611 string is the content of I<stderr> from the command.
1612
1613 The C<$PATH> environment variable will contain at least
1614 C</usr/bin> and C</bin>.  If you require a program from
1615 another location, you should provide the full path in the
1616 first parameter.
1617
1618 Shared libraries and data files required by the program
1619 must be available on filesystems which are mounted in the
1620 correct places.  It is the caller's responsibility to ensure
1621 all filesystems that are needed are mounted at the right
1622 locations.");
1623
1624   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1625    [InitBasicFS, Always, TestOutputList (
1626       [["upload"; "test-command"; "/test-command"];
1627        ["chmod"; "0o755"; "/test-command"];
1628        ["command_lines"; "/test-command 1"]], ["Result1"]);
1629     InitBasicFS, Always, TestOutputList (
1630       [["upload"; "test-command"; "/test-command"];
1631        ["chmod"; "0o755"; "/test-command"];
1632        ["command_lines"; "/test-command 2"]], ["Result2"]);
1633     InitBasicFS, Always, TestOutputList (
1634       [["upload"; "test-command"; "/test-command"];
1635        ["chmod"; "0o755"; "/test-command"];
1636        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1637     InitBasicFS, Always, TestOutputList (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1641     InitBasicFS, Always, TestOutputList (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1645     InitBasicFS, Always, TestOutputList (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1649     InitBasicFS, Always, TestOutputList (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command_lines"; "/test-command 7"]], []);
1653     InitBasicFS, Always, TestOutputList (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command_lines"; "/test-command 8"]], [""]);
1657     InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 9"]], ["";""]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1669    "run a command, returning lines",
1670    "\
1671 This is the same as C<guestfs_command>, but splits the
1672 result into a list of lines.
1673
1674 See also: C<guestfs_sh_lines>");
1675
1676   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1677    [InitISOFS, Always, TestOutputStruct (
1678       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1679    "get file information",
1680    "\
1681 Returns file information for the given C<path>.
1682
1683 This is the same as the C<stat(2)> system call.");
1684
1685   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1686    [InitISOFS, Always, TestOutputStruct (
1687       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1688    "get file information for a symbolic link",
1689    "\
1690 Returns file information for the given C<path>.
1691
1692 This is the same as C<guestfs_stat> except that if C<path>
1693 is a symbolic link, then the link is stat-ed, not the file it
1694 refers to.
1695
1696 This is the same as the C<lstat(2)> system call.");
1697
1698   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1699    [InitISOFS, Always, TestOutputStruct (
1700       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1701    "get file system statistics",
1702    "\
1703 Returns file system statistics for any mounted file system.
1704 C<path> should be a file or directory in the mounted file system
1705 (typically it is the mount point itself, but it doesn't need to be).
1706
1707 This is the same as the C<statvfs(2)> system call.");
1708
1709   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1710    [], (* XXX test *)
1711    "get ext2/ext3/ext4 superblock details",
1712    "\
1713 This returns the contents of the ext2, ext3 or ext4 filesystem
1714 superblock on C<device>.
1715
1716 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1717 manpage for more details.  The list of fields returned isn't
1718 clearly defined, and depends on both the version of C<tune2fs>
1719 that libguestfs was built against, and the filesystem itself.");
1720
1721   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1722    [InitEmpty, Always, TestOutputTrue (
1723       [["blockdev_setro"; "/dev/sda"];
1724        ["blockdev_getro"; "/dev/sda"]])],
1725    "set block device to read-only",
1726    "\
1727 Sets the block device named C<device> to read-only.
1728
1729 This uses the L<blockdev(8)> command.");
1730
1731   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1732    [InitEmpty, Always, TestOutputFalse (
1733       [["blockdev_setrw"; "/dev/sda"];
1734        ["blockdev_getro"; "/dev/sda"]])],
1735    "set block device to read-write",
1736    "\
1737 Sets the block device named C<device> to read-write.
1738
1739 This uses the L<blockdev(8)> command.");
1740
1741   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1742    [InitEmpty, Always, TestOutputTrue (
1743       [["blockdev_setro"; "/dev/sda"];
1744        ["blockdev_getro"; "/dev/sda"]])],
1745    "is block device set to read-only",
1746    "\
1747 Returns a boolean indicating if the block device is read-only
1748 (true if read-only, false if not).
1749
1750 This uses the L<blockdev(8)> command.");
1751
1752   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1753    [InitEmpty, Always, TestOutputInt (
1754       [["blockdev_getss"; "/dev/sda"]], 512)],
1755    "get sectorsize of block device",
1756    "\
1757 This returns the size of sectors on a block device.
1758 Usually 512, but can be larger for modern devices.
1759
1760 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1761 for that).
1762
1763 This uses the L<blockdev(8)> command.");
1764
1765   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1766    [InitEmpty, Always, TestOutputInt (
1767       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1768    "get blocksize of block device",
1769    "\
1770 This returns the block size of a device.
1771
1772 (Note this is different from both I<size in blocks> and
1773 I<filesystem block size>).
1774
1775 This uses the L<blockdev(8)> command.");
1776
1777   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1778    [], (* XXX test *)
1779    "set blocksize of block device",
1780    "\
1781 This sets the block size of a device.
1782
1783 (Note this is different from both I<size in blocks> and
1784 I<filesystem block size>).
1785
1786 This uses the L<blockdev(8)> command.");
1787
1788   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1789    [InitEmpty, Always, TestOutputInt (
1790       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1791    "get total size of device in 512-byte sectors",
1792    "\
1793 This returns the size of the device in units of 512-byte sectors
1794 (even if the sectorsize isn't 512 bytes ... weird).
1795
1796 See also C<guestfs_blockdev_getss> for the real sector size of
1797 the device, and C<guestfs_blockdev_getsize64> for the more
1798 useful I<size in bytes>.
1799
1800 This uses the L<blockdev(8)> command.");
1801
1802   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1803    [InitEmpty, Always, TestOutputInt (
1804       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1805    "get total size of device in bytes",
1806    "\
1807 This returns the size of the device in bytes.
1808
1809 See also C<guestfs_blockdev_getsz>.
1810
1811 This uses the L<blockdev(8)> command.");
1812
1813   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1814    [InitEmpty, Always, TestRun
1815       [["blockdev_flushbufs"; "/dev/sda"]]],
1816    "flush device buffers",
1817    "\
1818 This tells the kernel to flush internal buffers associated
1819 with C<device>.
1820
1821 This uses the L<blockdev(8)> command.");
1822
1823   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1824    [InitEmpty, Always, TestRun
1825       [["blockdev_rereadpt"; "/dev/sda"]]],
1826    "reread partition table",
1827    "\
1828 Reread the partition table on C<device>.
1829
1830 This uses the L<blockdev(8)> command.");
1831
1832   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1833    [InitBasicFS, Always, TestOutput (
1834       (* Pick a file from cwd which isn't likely to change. *)
1835       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1836        ["checksum"; "md5"; "/COPYING.LIB"]],
1837         Digest.to_hex (Digest.file "COPYING.LIB"))],
1838    "upload a file from the local machine",
1839    "\
1840 Upload local file C<filename> to C<remotefilename> on the
1841 filesystem.
1842
1843 C<filename> can also be a named pipe.
1844
1845 See also C<guestfs_download>.");
1846
1847   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1848    [InitBasicFS, Always, TestOutput (
1849       (* Pick a file from cwd which isn't likely to change. *)
1850       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1851        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1852        ["upload"; "testdownload.tmp"; "/upload"];
1853        ["checksum"; "md5"; "/upload"]],
1854         Digest.to_hex (Digest.file "COPYING.LIB"))],
1855    "download a file to the local machine",
1856    "\
1857 Download file C<remotefilename> and save it as C<filename>
1858 on the local machine.
1859
1860 C<filename> can also be a named pipe.
1861
1862 See also C<guestfs_upload>, C<guestfs_cat>.");
1863
1864   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1865    [InitISOFS, Always, TestOutput (
1866       [["checksum"; "crc"; "/known-3"]], "2891671662");
1867     InitISOFS, Always, TestLastFail (
1868       [["checksum"; "crc"; "/notexists"]]);
1869     InitISOFS, Always, TestOutput (
1870       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1879     InitISOFS, Always, TestOutput (
1880       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1881    "compute MD5, SHAx or CRC checksum of file",
1882    "\
1883 This call computes the MD5, SHAx or CRC checksum of the
1884 file named C<path>.
1885
1886 The type of checksum to compute is given by the C<csumtype>
1887 parameter which must have one of the following values:
1888
1889 =over 4
1890
1891 =item C<crc>
1892
1893 Compute the cyclic redundancy check (CRC) specified by POSIX
1894 for the C<cksum> command.
1895
1896 =item C<md5>
1897
1898 Compute the MD5 hash (using the C<md5sum> program).
1899
1900 =item C<sha1>
1901
1902 Compute the SHA1 hash (using the C<sha1sum> program).
1903
1904 =item C<sha224>
1905
1906 Compute the SHA224 hash (using the C<sha224sum> program).
1907
1908 =item C<sha256>
1909
1910 Compute the SHA256 hash (using the C<sha256sum> program).
1911
1912 =item C<sha384>
1913
1914 Compute the SHA384 hash (using the C<sha384sum> program).
1915
1916 =item C<sha512>
1917
1918 Compute the SHA512 hash (using the C<sha512sum> program).
1919
1920 =back
1921
1922 The checksum is returned as a printable string.");
1923
1924   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1925    [InitBasicFS, Always, TestOutput (
1926       [["tar_in"; "../images/helloworld.tar"; "/"];
1927        ["cat"; "/hello"]], "hello\n")],
1928    "unpack tarfile to directory",
1929    "\
1930 This command uploads and unpacks local file C<tarfile> (an
1931 I<uncompressed> tar file) into C<directory>.
1932
1933 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1934
1935   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1936    [],
1937    "pack directory into tarfile",
1938    "\
1939 This command packs the contents of C<directory> and downloads
1940 it to local file C<tarfile>.
1941
1942 To download a compressed tarball, use C<guestfs_tgz_out>.");
1943
1944   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1945    [InitBasicFS, Always, TestOutput (
1946       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1947        ["cat"; "/hello"]], "hello\n")],
1948    "unpack compressed tarball to directory",
1949    "\
1950 This command uploads and unpacks local file C<tarball> (a
1951 I<gzip compressed> tar file) into C<directory>.
1952
1953 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1954
1955   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1956    [],
1957    "pack directory into compressed tarball",
1958    "\
1959 This command packs the contents of C<directory> and downloads
1960 it to local file C<tarball>.
1961
1962 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1963
1964   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1965    [InitBasicFS, Always, TestLastFail (
1966       [["umount"; "/"];
1967        ["mount_ro"; "/dev/sda1"; "/"];
1968        ["touch"; "/new"]]);
1969     InitBasicFS, Always, TestOutput (
1970       [["write_file"; "/new"; "data"; "0"];
1971        ["umount"; "/"];
1972        ["mount_ro"; "/dev/sda1"; "/"];
1973        ["cat"; "/new"]], "data")],
1974    "mount a guest disk, read-only",
1975    "\
1976 This is the same as the C<guestfs_mount> command, but it
1977 mounts the filesystem with the read-only (I<-o ro>) flag.");
1978
1979   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1980    [],
1981    "mount a guest disk with mount options",
1982    "\
1983 This is the same as the C<guestfs_mount> command, but it
1984 allows you to set the mount options as for the
1985 L<mount(8)> I<-o> flag.");
1986
1987   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1988    [],
1989    "mount a guest disk with mount options and vfstype",
1990    "\
1991 This is the same as the C<guestfs_mount> command, but it
1992 allows you to set both the mount options and the vfstype
1993 as for the L<mount(8)> I<-o> and I<-t> flags.");
1994
1995   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1996    [],
1997    "debugging and internals",
1998    "\
1999 The C<guestfs_debug> command exposes some internals of
2000 C<guestfsd> (the guestfs daemon) that runs inside the
2001 qemu subprocess.
2002
2003 There is no comprehensive help for this command.  You have
2004 to look at the file C<daemon/debug.c> in the libguestfs source
2005 to find out what you can do.");
2006
2007   ("lvremove", (RErr, [Device "device"]), 77, [],
2008    [InitEmpty, Always, TestOutputList (
2009       [["sfdiskM"; "/dev/sda"; ","];
2010        ["pvcreate"; "/dev/sda1"];
2011        ["vgcreate"; "VG"; "/dev/sda1"];
2012        ["lvcreate"; "LV1"; "VG"; "50"];
2013        ["lvcreate"; "LV2"; "VG"; "50"];
2014        ["lvremove"; "/dev/VG/LV1"];
2015        ["lvs"]], ["/dev/VG/LV2"]);
2016     InitEmpty, Always, TestOutputList (
2017       [["sfdiskM"; "/dev/sda"; ","];
2018        ["pvcreate"; "/dev/sda1"];
2019        ["vgcreate"; "VG"; "/dev/sda1"];
2020        ["lvcreate"; "LV1"; "VG"; "50"];
2021        ["lvcreate"; "LV2"; "VG"; "50"];
2022        ["lvremove"; "/dev/VG"];
2023        ["lvs"]], []);
2024     InitEmpty, Always, TestOutputList (
2025       [["sfdiskM"; "/dev/sda"; ","];
2026        ["pvcreate"; "/dev/sda1"];
2027        ["vgcreate"; "VG"; "/dev/sda1"];
2028        ["lvcreate"; "LV1"; "VG"; "50"];
2029        ["lvcreate"; "LV2"; "VG"; "50"];
2030        ["lvremove"; "/dev/VG"];
2031        ["vgs"]], ["VG"])],
2032    "remove an LVM logical volume",
2033    "\
2034 Remove an LVM logical volume C<device>, where C<device> is
2035 the path to the LV, such as C</dev/VG/LV>.
2036
2037 You can also remove all LVs in a volume group by specifying
2038 the VG name, C</dev/VG>.");
2039
2040   ("vgremove", (RErr, [String "vgname"]), 78, [],
2041    [InitEmpty, Always, TestOutputList (
2042       [["sfdiskM"; "/dev/sda"; ","];
2043        ["pvcreate"; "/dev/sda1"];
2044        ["vgcreate"; "VG"; "/dev/sda1"];
2045        ["lvcreate"; "LV1"; "VG"; "50"];
2046        ["lvcreate"; "LV2"; "VG"; "50"];
2047        ["vgremove"; "VG"];
2048        ["lvs"]], []);
2049     InitEmpty, Always, TestOutputList (
2050       [["sfdiskM"; "/dev/sda"; ","];
2051        ["pvcreate"; "/dev/sda1"];
2052        ["vgcreate"; "VG"; "/dev/sda1"];
2053        ["lvcreate"; "LV1"; "VG"; "50"];
2054        ["lvcreate"; "LV2"; "VG"; "50"];
2055        ["vgremove"; "VG"];
2056        ["vgs"]], [])],
2057    "remove an LVM volume group",
2058    "\
2059 Remove an LVM volume group C<vgname>, (for example C<VG>).
2060
2061 This also forcibly removes all logical volumes in the volume
2062 group (if any).");
2063
2064   ("pvremove", (RErr, [Device "device"]), 79, [],
2065    [InitEmpty, Always, TestOutputListOfDevices (
2066       [["sfdiskM"; "/dev/sda"; ","];
2067        ["pvcreate"; "/dev/sda1"];
2068        ["vgcreate"; "VG"; "/dev/sda1"];
2069        ["lvcreate"; "LV1"; "VG"; "50"];
2070        ["lvcreate"; "LV2"; "VG"; "50"];
2071        ["vgremove"; "VG"];
2072        ["pvremove"; "/dev/sda1"];
2073        ["lvs"]], []);
2074     InitEmpty, Always, TestOutputListOfDevices (
2075       [["sfdiskM"; "/dev/sda"; ","];
2076        ["pvcreate"; "/dev/sda1"];
2077        ["vgcreate"; "VG"; "/dev/sda1"];
2078        ["lvcreate"; "LV1"; "VG"; "50"];
2079        ["lvcreate"; "LV2"; "VG"; "50"];
2080        ["vgremove"; "VG"];
2081        ["pvremove"; "/dev/sda1"];
2082        ["vgs"]], []);
2083     InitEmpty, Always, TestOutputListOfDevices (
2084       [["sfdiskM"; "/dev/sda"; ","];
2085        ["pvcreate"; "/dev/sda1"];
2086        ["vgcreate"; "VG"; "/dev/sda1"];
2087        ["lvcreate"; "LV1"; "VG"; "50"];
2088        ["lvcreate"; "LV2"; "VG"; "50"];
2089        ["vgremove"; "VG"];
2090        ["pvremove"; "/dev/sda1"];
2091        ["pvs"]], [])],
2092    "remove an LVM physical volume",
2093    "\
2094 This wipes a physical volume C<device> so that LVM will no longer
2095 recognise it.
2096
2097 The implementation uses the C<pvremove> command which refuses to
2098 wipe physical volumes that contain any volume groups, so you have
2099 to remove those first.");
2100
2101   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2102    [InitBasicFS, Always, TestOutput (
2103       [["set_e2label"; "/dev/sda1"; "testlabel"];
2104        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2105    "set the ext2/3/4 filesystem label",
2106    "\
2107 This sets the ext2/3/4 filesystem label of the filesystem on
2108 C<device> to C<label>.  Filesystem labels are limited to
2109 16 characters.
2110
2111 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2112 to return the existing label on a filesystem.");
2113
2114   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2115    [],
2116    "get the ext2/3/4 filesystem label",
2117    "\
2118 This returns the ext2/3/4 filesystem label of the filesystem on
2119 C<device>.");
2120
2121   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2122    (let uuid = uuidgen () in
2123     [InitBasicFS, Always, TestOutput (
2124        [["set_e2uuid"; "/dev/sda1"; uuid];
2125         ["get_e2uuid"; "/dev/sda1"]], uuid);
2126      InitBasicFS, Always, TestOutput (
2127        [["set_e2uuid"; "/dev/sda1"; "clear"];
2128         ["get_e2uuid"; "/dev/sda1"]], "");
2129      (* We can't predict what UUIDs will be, so just check the commands run. *)
2130      InitBasicFS, Always, TestRun (
2131        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2132      InitBasicFS, Always, TestRun (
2133        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2134    "set the ext2/3/4 filesystem UUID",
2135    "\
2136 This sets the ext2/3/4 filesystem UUID of the filesystem on
2137 C<device> to C<uuid>.  The format of the UUID and alternatives
2138 such as C<clear>, C<random> and C<time> are described in the
2139 L<tune2fs(8)> manpage.
2140
2141 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2142 to return the existing UUID of a filesystem.");
2143
2144   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2145    [],
2146    "get the ext2/3/4 filesystem UUID",
2147    "\
2148 This returns the ext2/3/4 filesystem UUID of the filesystem on
2149 C<device>.");
2150
2151   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2152    [InitBasicFS, Always, TestOutputInt (
2153       [["umount"; "/dev/sda1"];
2154        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2155     InitBasicFS, Always, TestOutputInt (
2156       [["umount"; "/dev/sda1"];
2157        ["zero"; "/dev/sda1"];
2158        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2159    "run the filesystem checker",
2160    "\
2161 This runs the filesystem checker (fsck) on C<device> which
2162 should have filesystem type C<fstype>.
2163
2164 The returned integer is the status.  See L<fsck(8)> for the
2165 list of status codes from C<fsck>.
2166
2167 Notes:
2168
2169 =over 4
2170
2171 =item *
2172
2173 Multiple status codes can be summed together.
2174
2175 =item *
2176
2177 A non-zero return code can mean \"success\", for example if
2178 errors have been corrected on the filesystem.
2179
2180 =item *
2181
2182 Checking or repairing NTFS volumes is not supported
2183 (by linux-ntfs).
2184
2185 =back
2186
2187 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2188
2189   ("zero", (RErr, [Device "device"]), 85, [],
2190    [InitBasicFS, Always, TestOutput (
2191       [["umount"; "/dev/sda1"];
2192        ["zero"; "/dev/sda1"];
2193        ["file"; "/dev/sda1"]], "data")],
2194    "write zeroes to the device",
2195    "\
2196 This command writes zeroes over the first few blocks of C<device>.
2197
2198 How many blocks are zeroed isn't specified (but it's I<not> enough
2199 to securely wipe the device).  It should be sufficient to remove
2200 any partition tables, filesystem superblocks and so on.
2201
2202 See also: C<guestfs_scrub_device>.");
2203
2204   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2205    (* Test disabled because grub-install incompatible with virtio-blk driver.
2206     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2207     *)
2208    [InitBasicFS, Disabled, TestOutputTrue (
2209       [["grub_install"; "/"; "/dev/sda1"];
2210        ["is_dir"; "/boot"]])],
2211    "install GRUB",
2212    "\
2213 This command installs GRUB (the Grand Unified Bootloader) on
2214 C<device>, with the root directory being C<root>.");
2215
2216   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2217    [InitBasicFS, Always, TestOutput (
2218       [["write_file"; "/old"; "file content"; "0"];
2219        ["cp"; "/old"; "/new"];
2220        ["cat"; "/new"]], "file content");
2221     InitBasicFS, Always, TestOutputTrue (
2222       [["write_file"; "/old"; "file content"; "0"];
2223        ["cp"; "/old"; "/new"];
2224        ["is_file"; "/old"]]);
2225     InitBasicFS, Always, TestOutput (
2226       [["write_file"; "/old"; "file content"; "0"];
2227        ["mkdir"; "/dir"];
2228        ["cp"; "/old"; "/dir/new"];
2229        ["cat"; "/dir/new"]], "file content")],
2230    "copy a file",
2231    "\
2232 This copies a file from C<src> to C<dest> where C<dest> is
2233 either a destination filename or destination directory.");
2234
2235   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2236    [InitBasicFS, Always, TestOutput (
2237       [["mkdir"; "/olddir"];
2238        ["mkdir"; "/newdir"];
2239        ["write_file"; "/olddir/file"; "file content"; "0"];
2240        ["cp_a"; "/olddir"; "/newdir"];
2241        ["cat"; "/newdir/olddir/file"]], "file content")],
2242    "copy a file or directory recursively",
2243    "\
2244 This copies a file or directory from C<src> to C<dest>
2245 recursively using the C<cp -a> command.");
2246
2247   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2248    [InitBasicFS, Always, TestOutput (
2249       [["write_file"; "/old"; "file content"; "0"];
2250        ["mv"; "/old"; "/new"];
2251        ["cat"; "/new"]], "file content");
2252     InitBasicFS, Always, TestOutputFalse (
2253       [["write_file"; "/old"; "file content"; "0"];
2254        ["mv"; "/old"; "/new"];
2255        ["is_file"; "/old"]])],
2256    "move a file",
2257    "\
2258 This moves a file from C<src> to C<dest> where C<dest> is
2259 either a destination filename or destination directory.");
2260
2261   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2262    [InitEmpty, Always, TestRun (
2263       [["drop_caches"; "3"]])],
2264    "drop kernel page cache, dentries and inodes",
2265    "\
2266 This instructs the guest kernel to drop its page cache,
2267 and/or dentries and inode caches.  The parameter C<whattodrop>
2268 tells the kernel what precisely to drop, see
2269 L<http://linux-mm.org/Drop_Caches>
2270
2271 Setting C<whattodrop> to 3 should drop everything.
2272
2273 This automatically calls L<sync(2)> before the operation,
2274 so that the maximum guest memory is freed.");
2275
2276   ("dmesg", (RString "kmsgs", []), 91, [],
2277    [InitEmpty, Always, TestRun (
2278       [["dmesg"]])],
2279    "return kernel messages",
2280    "\
2281 This returns the kernel messages (C<dmesg> output) from
2282 the guest kernel.  This is sometimes useful for extended
2283 debugging of problems.
2284
2285 Another way to get the same information is to enable
2286 verbose messages with C<guestfs_set_verbose> or by setting
2287 the environment variable C<LIBGUESTFS_DEBUG=1> before
2288 running the program.");
2289
2290   ("ping_daemon", (RErr, []), 92, [],
2291    [InitEmpty, Always, TestRun (
2292       [["ping_daemon"]])],
2293    "ping the guest daemon",
2294    "\
2295 This is a test probe into the guestfs daemon running inside
2296 the qemu subprocess.  Calling this function checks that the
2297 daemon responds to the ping message, without affecting the daemon
2298 or attached block device(s) in any other way.");
2299
2300   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2301    [InitBasicFS, Always, TestOutputTrue (
2302       [["write_file"; "/file1"; "contents of a file"; "0"];
2303        ["cp"; "/file1"; "/file2"];
2304        ["equal"; "/file1"; "/file2"]]);
2305     InitBasicFS, Always, TestOutputFalse (
2306       [["write_file"; "/file1"; "contents of a file"; "0"];
2307        ["write_file"; "/file2"; "contents of another file"; "0"];
2308        ["equal"; "/file1"; "/file2"]]);
2309     InitBasicFS, Always, TestLastFail (
2310       [["equal"; "/file1"; "/file2"]])],
2311    "test if two files have equal contents",
2312    "\
2313 This compares the two files C<file1> and C<file2> and returns
2314 true if their content is exactly equal, or false otherwise.
2315
2316 The external L<cmp(1)> program is used for the comparison.");
2317
2318   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2319    [InitISOFS, Always, TestOutputList (
2320       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2321     InitISOFS, Always, TestOutputList (
2322       [["strings"; "/empty"]], [])],
2323    "print the printable strings in a file",
2324    "\
2325 This runs the L<strings(1)> command on a file and returns
2326 the list of printable strings found.");
2327
2328   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2329    [InitISOFS, Always, TestOutputList (
2330       [["strings_e"; "b"; "/known-5"]], []);
2331     InitBasicFS, Disabled, TestOutputList (
2332       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2333        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2334    "print the printable strings in a file",
2335    "\
2336 This is like the C<guestfs_strings> command, but allows you to
2337 specify the encoding.
2338
2339 See the L<strings(1)> manpage for the full list of encodings.
2340
2341 Commonly useful encodings are C<l> (lower case L) which will
2342 show strings inside Windows/x86 files.
2343
2344 The returned strings are transcoded to UTF-8.");
2345
2346   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2347    [InitISOFS, Always, TestOutput (
2348       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2349     (* Test for RHBZ#501888c2 regression which caused large hexdump
2350      * commands to segfault.
2351      *)
2352     InitISOFS, Always, TestRun (
2353       [["hexdump"; "/100krandom"]])],
2354    "dump a file in hexadecimal",
2355    "\
2356 This runs C<hexdump -C> on the given C<path>.  The result is
2357 the human-readable, canonical hex dump of the file.");
2358
2359   ("zerofree", (RErr, [Device "device"]), 97, [],
2360    [InitNone, Always, TestOutput (
2361       [["sfdiskM"; "/dev/sda"; ","];
2362        ["mkfs"; "ext3"; "/dev/sda1"];
2363        ["mount"; "/dev/sda1"; "/"];
2364        ["write_file"; "/new"; "test file"; "0"];
2365        ["umount"; "/dev/sda1"];
2366        ["zerofree"; "/dev/sda1"];
2367        ["mount"; "/dev/sda1"; "/"];
2368        ["cat"; "/new"]], "test file")],
2369    "zero unused inodes and disk blocks on ext2/3 filesystem",
2370    "\
2371 This runs the I<zerofree> program on C<device>.  This program
2372 claims to zero unused inodes and disk blocks on an ext2/3
2373 filesystem, thus making it possible to compress the filesystem
2374 more effectively.
2375
2376 You should B<not> run this program if the filesystem is
2377 mounted.
2378
2379 It is possible that using this program can damage the filesystem
2380 or data on the filesystem.");
2381
2382   ("pvresize", (RErr, [Device "device"]), 98, [],
2383    [],
2384    "resize an LVM physical volume",
2385    "\
2386 This resizes (expands or shrinks) an existing LVM physical
2387 volume to match the new size of the underlying device.");
2388
2389   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2390                        Int "cyls"; Int "heads"; Int "sectors";
2391                        String "line"]), 99, [DangerWillRobinson],
2392    [],
2393    "modify a single partition on a block device",
2394    "\
2395 This runs L<sfdisk(8)> option to modify just the single
2396 partition C<n> (note: C<n> counts from 1).
2397
2398 For other parameters, see C<guestfs_sfdisk>.  You should usually
2399 pass C<0> for the cyls/heads/sectors parameters.");
2400
2401   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2402    [],
2403    "display the partition table",
2404    "\
2405 This displays the partition table on C<device>, in the
2406 human-readable output of the L<sfdisk(8)> command.  It is
2407 not intended to be parsed.");
2408
2409   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2410    [],
2411    "display the kernel geometry",
2412    "\
2413 This displays the kernel's idea of the geometry of C<device>.
2414
2415 The result is in human-readable format, and not designed to
2416 be parsed.");
2417
2418   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2419    [],
2420    "display the disk geometry from the partition table",
2421    "\
2422 This displays the disk geometry of C<device> read from the
2423 partition table.  Especially in the case where the underlying
2424 block device has been resized, this can be different from the
2425 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2426
2427 The result is in human-readable format, and not designed to
2428 be parsed.");
2429
2430   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2431    [],
2432    "activate or deactivate all volume groups",
2433    "\
2434 This command activates or (if C<activate> is false) deactivates
2435 all logical volumes in all volume groups.
2436 If activated, then they are made known to the
2437 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2438 then those devices disappear.
2439
2440 This command is the same as running C<vgchange -a y|n>");
2441
2442   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2443    [],
2444    "activate or deactivate some volume groups",
2445    "\
2446 This command activates or (if C<activate> is false) deactivates
2447 all logical volumes in the listed volume groups C<volgroups>.
2448 If activated, then they are made known to the
2449 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2450 then those devices disappear.
2451
2452 This command is the same as running C<vgchange -a y|n volgroups...>
2453
2454 Note that if C<volgroups> is an empty list then B<all> volume groups
2455 are activated or deactivated.");
2456
2457   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2458    [InitNone, Always, TestOutput (
2459       [["sfdiskM"; "/dev/sda"; ","];
2460        ["pvcreate"; "/dev/sda1"];
2461        ["vgcreate"; "VG"; "/dev/sda1"];
2462        ["lvcreate"; "LV"; "VG"; "10"];
2463        ["mkfs"; "ext2"; "/dev/VG/LV"];
2464        ["mount"; "/dev/VG/LV"; "/"];
2465        ["write_file"; "/new"; "test content"; "0"];
2466        ["umount"; "/"];
2467        ["lvresize"; "/dev/VG/LV"; "20"];
2468        ["e2fsck_f"; "/dev/VG/LV"];
2469        ["resize2fs"; "/dev/VG/LV"];
2470        ["mount"; "/dev/VG/LV"; "/"];
2471        ["cat"; "/new"]], "test content")],
2472    "resize an LVM logical volume",
2473    "\
2474 This resizes (expands or shrinks) an existing LVM logical
2475 volume to C<mbytes>.  When reducing, data in the reduced part
2476 is lost.");
2477
2478   ("resize2fs", (RErr, [Device "device"]), 106, [],
2479    [], (* lvresize tests this *)
2480    "resize an ext2/ext3 filesystem",
2481    "\
2482 This resizes an ext2 or ext3 filesystem to match the size of
2483 the underlying device.
2484
2485 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2486 on the C<device> before calling this command.  For unknown reasons
2487 C<resize2fs> sometimes gives an error about this and sometimes not.
2488 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2489 calling this function.");
2490
2491   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2492    [InitBasicFS, Always, TestOutputList (
2493       [["find"; "/"]], ["lost+found"]);
2494     InitBasicFS, Always, TestOutputList (
2495       [["touch"; "/a"];
2496        ["mkdir"; "/b"];
2497        ["touch"; "/b/c"];
2498        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2499     InitBasicFS, Always, TestOutputList (
2500       [["mkdir_p"; "/a/b/c"];
2501        ["touch"; "/a/b/c/d"];
2502        ["find"; "/a/b/"]], ["c"; "c/d"])],
2503    "find all files and directories",
2504    "\
2505 This command lists out all files and directories, recursively,
2506 starting at C<directory>.  It is essentially equivalent to
2507 running the shell command C<find directory -print> but some
2508 post-processing happens on the output, described below.
2509
2510 This returns a list of strings I<without any prefix>.  Thus
2511 if the directory structure was:
2512
2513  /tmp/a
2514  /tmp/b
2515  /tmp/c/d
2516
2517 then the returned list from C<guestfs_find> C</tmp> would be
2518 4 elements:
2519
2520  a
2521  b
2522  c
2523  c/d
2524
2525 If C<directory> is not a directory, then this command returns
2526 an error.
2527
2528 The returned list is sorted.
2529
2530 See also C<guestfs_find0>.");
2531
2532   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2533    [], (* lvresize tests this *)
2534    "check an ext2/ext3 filesystem",
2535    "\
2536 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2537 filesystem checker on C<device>, noninteractively (C<-p>),
2538 even if the filesystem appears to be clean (C<-f>).
2539
2540 This command is only needed because of C<guestfs_resize2fs>
2541 (q.v.).  Normally you should use C<guestfs_fsck>.");
2542
2543   ("sleep", (RErr, [Int "secs"]), 109, [],
2544    [InitNone, Always, TestRun (
2545       [["sleep"; "1"]])],
2546    "sleep for some seconds",
2547    "\
2548 Sleep for C<secs> seconds.");
2549
2550   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2551    [InitNone, Always, TestOutputInt (
2552       [["sfdiskM"; "/dev/sda"; ","];
2553        ["mkfs"; "ntfs"; "/dev/sda1"];
2554        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2555     InitNone, Always, TestOutputInt (
2556       [["sfdiskM"; "/dev/sda"; ","];
2557        ["mkfs"; "ext2"; "/dev/sda1"];
2558        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2559    "probe NTFS volume",
2560    "\
2561 This command runs the L<ntfs-3g.probe(8)> command which probes
2562 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2563 be mounted read-write, and some cannot be mounted at all).
2564
2565 C<rw> is a boolean flag.  Set it to true if you want to test
2566 if the volume can be mounted read-write.  Set it to false if
2567 you want to test if the volume can be mounted read-only.
2568
2569 The return value is an integer which C<0> if the operation
2570 would succeed, or some non-zero value documented in the
2571 L<ntfs-3g.probe(8)> manual page.");
2572
2573   ("sh", (RString "output", [String "command"]), 111, [],
2574    [], (* XXX needs tests *)
2575    "run a command via the shell",
2576    "\
2577 This call runs a command from the guest filesystem via the
2578 guest's C</bin/sh>.
2579
2580 This is like C<guestfs_command>, but passes the command to:
2581
2582  /bin/sh -c \"command\"
2583
2584 Depending on the guest's shell, this usually results in
2585 wildcards being expanded, shell expressions being interpolated
2586 and so on.
2587
2588 All the provisos about C<guestfs_command> apply to this call.");
2589
2590   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2591    [], (* XXX needs tests *)
2592    "run a command via the shell returning lines",
2593    "\
2594 This is the same as C<guestfs_sh>, but splits the result
2595 into a list of lines.
2596
2597 See also: C<guestfs_command_lines>");
2598
2599   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2600    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2601     * code in stubs.c, since all valid glob patterns must start with "/".
2602     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2603     *)
2604    [InitBasicFS, Always, TestOutputList (
2605       [["mkdir_p"; "/a/b/c"];
2606        ["touch"; "/a/b/c/d"];
2607        ["touch"; "/a/b/c/e"];
2608        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2609     InitBasicFS, Always, TestOutputList (
2610       [["mkdir_p"; "/a/b/c"];
2611        ["touch"; "/a/b/c/d"];
2612        ["touch"; "/a/b/c/e"];
2613        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2614     InitBasicFS, Always, TestOutputList (
2615       [["mkdir_p"; "/a/b/c"];
2616        ["touch"; "/a/b/c/d"];
2617        ["touch"; "/a/b/c/e"];
2618        ["glob_expand"; "/a/*/x/*"]], [])],
2619    "expand a wildcard path",
2620    "\
2621 This command searches for all the pathnames matching
2622 C<pattern> according to the wildcard expansion rules
2623 used by the shell.
2624
2625 If no paths match, then this returns an empty list
2626 (note: not an error).
2627
2628 It is just a wrapper around the C L<glob(3)> function
2629 with flags C<GLOB_MARK|GLOB_BRACE>.
2630 See that manual page for more details.");
2631
2632   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2633    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2634       [["scrub_device"; "/dev/sdc"]])],
2635    "scrub (securely wipe) a device",
2636    "\
2637 This command writes patterns over C<device> to make data retrieval
2638 more difficult.
2639
2640 It is an interface to the L<scrub(1)> program.  See that
2641 manual page for more details.");
2642
2643   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2644    [InitBasicFS, Always, TestRun (
2645       [["write_file"; "/file"; "content"; "0"];
2646        ["scrub_file"; "/file"]])],
2647    "scrub (securely wipe) a file",
2648    "\
2649 This command writes patterns over a file to make data retrieval
2650 more difficult.
2651
2652 The file is I<removed> after scrubbing.
2653
2654 It is an interface to the L<scrub(1)> program.  See that
2655 manual page for more details.");
2656
2657   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2658    [], (* XXX needs testing *)
2659    "scrub (securely wipe) free space",
2660    "\
2661 This command creates the directory C<dir> and then fills it
2662 with files until the filesystem is full, and scrubs the files
2663 as for C<guestfs_scrub_file>, and deletes them.
2664 The intention is to scrub any free space on the partition
2665 containing C<dir>.
2666
2667 It is an interface to the L<scrub(1)> program.  See that
2668 manual page for more details.");
2669
2670   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2671    [InitBasicFS, Always, TestRun (
2672       [["mkdir"; "/tmp"];
2673        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2674    "create a temporary directory",
2675    "\
2676 This command creates a temporary directory.  The
2677 C<template> parameter should be a full pathname for the
2678 temporary directory name with the final six characters being
2679 \"XXXXXX\".
2680
2681 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2682 the second one being suitable for Windows filesystems.
2683
2684 The name of the temporary directory that was created
2685 is returned.
2686
2687 The temporary directory is created with mode 0700
2688 and is owned by root.
2689
2690 The caller is responsible for deleting the temporary
2691 directory and its contents after use.
2692
2693 See also: L<mkdtemp(3)>");
2694
2695   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2696    [InitISOFS, Always, TestOutputInt (
2697       [["wc_l"; "/10klines"]], 10000)],
2698    "count lines in a file",
2699    "\
2700 This command counts the lines in a file, using the
2701 C<wc -l> external command.");
2702
2703   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2704    [InitISOFS, Always, TestOutputInt (
2705       [["wc_w"; "/10klines"]], 10000)],
2706    "count words in a file",
2707    "\
2708 This command counts the words in a file, using the
2709 C<wc -w> external command.");
2710
2711   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2712    [InitISOFS, Always, TestOutputInt (
2713       [["wc_c"; "/100kallspaces"]], 102400)],
2714    "count characters in a file",
2715    "\
2716 This command counts the characters in a file, using the
2717 C<wc -c> external command.");
2718
2719   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2720    [InitISOFS, Always, TestOutputList (
2721       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2722    "return first 10 lines of a file",
2723    "\
2724 This command returns up to the first 10 lines of a file as
2725 a list of strings.");
2726
2727   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2728    [InitISOFS, Always, TestOutputList (
2729       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2730     InitISOFS, Always, TestOutputList (
2731       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732     InitISOFS, Always, TestOutputList (
2733       [["head_n"; "0"; "/10klines"]], [])],
2734    "return first N lines of a file",
2735    "\
2736 If the parameter C<nrlines> is a positive number, this returns the first
2737 C<nrlines> lines of the file C<path>.
2738
2739 If the parameter C<nrlines> is a negative number, this returns lines
2740 from the file C<path>, excluding the last C<nrlines> lines.
2741
2742 If the parameter C<nrlines> is zero, this returns an empty list.");
2743
2744   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2745    [InitISOFS, Always, TestOutputList (
2746       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2747    "return last 10 lines of a file",
2748    "\
2749 This command returns up to the last 10 lines of a file as
2750 a list of strings.");
2751
2752   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2753    [InitISOFS, Always, TestOutputList (
2754       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2755     InitISOFS, Always, TestOutputList (
2756       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757     InitISOFS, Always, TestOutputList (
2758       [["tail_n"; "0"; "/10klines"]], [])],
2759    "return last N lines of a file",
2760    "\
2761 If the parameter C<nrlines> is a positive number, this returns the last
2762 C<nrlines> lines of the file C<path>.
2763
2764 If the parameter C<nrlines> is a negative number, this returns lines
2765 from the file C<path>, starting with the C<-nrlines>th line.
2766
2767 If the parameter C<nrlines> is zero, this returns an empty list.");
2768
2769   ("df", (RString "output", []), 125, [],
2770    [], (* XXX Tricky to test because it depends on the exact format
2771         * of the 'df' command and other imponderables.
2772         *)
2773    "report file system disk space usage",
2774    "\
2775 This command runs the C<df> command to report disk space used.
2776
2777 This command is mostly useful for interactive sessions.  It
2778 is I<not> intended that you try to parse the output string.
2779 Use C<statvfs> from programs.");
2780
2781   ("df_h", (RString "output", []), 126, [],
2782    [], (* XXX Tricky to test because it depends on the exact format
2783         * of the 'df' command and other imponderables.
2784         *)
2785    "report file system disk space usage (human readable)",
2786    "\
2787 This command runs the C<df -h> command to report disk space used
2788 in human-readable format.
2789
2790 This command is mostly useful for interactive sessions.  It
2791 is I<not> intended that you try to parse the output string.
2792 Use C<statvfs> from programs.");
2793
2794   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2797    "estimate file space usage",
2798    "\
2799 This command runs the C<du -s> command to estimate file space
2800 usage for C<path>.
2801
2802 C<path> can be a file or a directory.  If C<path> is a directory
2803 then the estimate includes the contents of the directory and all
2804 subdirectories (recursively).
2805
2806 The result is the estimated size in I<kilobytes>
2807 (ie. units of 1024 bytes).");
2808
2809   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2810    [InitISOFS, Always, TestOutputList (
2811       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2812    "list files in an initrd",
2813    "\
2814 This command lists out files contained in an initrd.
2815
2816 The files are listed without any initial C</> character.  The
2817 files are listed in the order they appear (not necessarily
2818 alphabetical).  Directory names are listed as separate items.
2819
2820 Old Linux kernels (2.4 and earlier) used a compressed ext2
2821 filesystem as initrd.  We I<only> support the newer initramfs
2822 format (compressed cpio files).");
2823
2824   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2825    [],
2826    "mount a file using the loop device",
2827    "\
2828 This command lets you mount C<file> (a filesystem image
2829 in a file) on a mount point.  It is entirely equivalent to
2830 the command C<mount -o loop file mountpoint>.");
2831
2832   ("mkswap", (RErr, [Device "device"]), 130, [],
2833    [InitEmpty, Always, TestRun (
2834       [["sfdiskM"; "/dev/sda"; ","];
2835        ["mkswap"; "/dev/sda1"]])],
2836    "create a swap partition",
2837    "\
2838 Create a swap partition on C<device>.");
2839
2840   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2841    [InitEmpty, Always, TestRun (
2842       [["sfdiskM"; "/dev/sda"; ","];
2843        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2844    "create a swap partition with a label",
2845    "\
2846 Create a swap partition on C<device> with label C<label>.
2847
2848 Note that you cannot attach a swap label to a block device
2849 (eg. C</dev/sda>), just to a partition.  This appears to be
2850 a limitation of the kernel or swap tools.");
2851
2852   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2853    (let uuid = uuidgen () in
2854     [InitEmpty, Always, TestRun (
2855        [["sfdiskM"; "/dev/sda"; ","];
2856         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2857    "create a swap partition with an explicit UUID",
2858    "\
2859 Create a swap partition on C<device> with UUID C<uuid>.");
2860
2861   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2862    [InitBasicFS, Always, TestOutputStruct (
2863       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2864        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2865        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2866     InitBasicFS, Always, TestOutputStruct (
2867       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2868        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2869    "make block, character or FIFO devices",
2870    "\
2871 This call creates block or character special devices, or
2872 named pipes (FIFOs).
2873
2874 The C<mode> parameter should be the mode, using the standard
2875 constants.  C<devmajor> and C<devminor> are the
2876 device major and minor numbers, only used when creating block
2877 and character special devices.");
2878
2879   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2880    [InitBasicFS, Always, TestOutputStruct (
2881       [["mkfifo"; "0o777"; "/node"];
2882        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2883    "make FIFO (named pipe)",
2884    "\
2885 This call creates a FIFO (named pipe) called C<path> with
2886 mode C<mode>.  It is just a convenient wrapper around
2887 C<guestfs_mknod>.");
2888
2889   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2890    [InitBasicFS, Always, TestOutputStruct (
2891       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2892        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2893    "make block device node",
2894    "\
2895 This call creates a block device node called C<path> with
2896 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2897 It is just a convenient wrapper around C<guestfs_mknod>.");
2898
2899   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2900    [InitBasicFS, Always, TestOutputStruct (
2901       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2902        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2903    "make char device node",
2904    "\
2905 This call creates a char device node called C<path> with
2906 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2907 It is just a convenient wrapper around C<guestfs_mknod>.");
2908
2909   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2910    [], (* XXX umask is one of those stateful things that we should
2911         * reset between each test.
2912         *)
2913    "set file mode creation mask (umask)",
2914    "\
2915 This function sets the mask used for creating new files and
2916 device nodes to C<mask & 0777>.
2917
2918 Typical umask values would be C<022> which creates new files
2919 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2920 C<002> which creates new files with permissions like
2921 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2922
2923 The default umask is C<022>.  This is important because it
2924 means that directories and device nodes will be created with
2925 C<0644> or C<0755> mode even if you specify C<0777>.
2926
2927 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2928
2929 This call returns the previous umask.");
2930
2931   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2932    [],
2933    "read directories entries",
2934    "\
2935 This returns the list of directory entries in directory C<dir>.
2936
2937 All entries in the directory are returned, including C<.> and
2938 C<..>.  The entries are I<not> sorted, but returned in the same
2939 order as the underlying filesystem.
2940
2941 Also this call returns basic file type information about each
2942 file.  The C<ftyp> field will contain one of the following characters:
2943
2944 =over 4
2945
2946 =item 'b'
2947
2948 Block special
2949
2950 =item 'c'
2951
2952 Char special
2953
2954 =item 'd'
2955
2956 Directory
2957
2958 =item 'f'
2959
2960 FIFO (named pipe)
2961
2962 =item 'l'
2963
2964 Symbolic link
2965
2966 =item 'r'
2967
2968 Regular file
2969
2970 =item 's'
2971
2972 Socket
2973
2974 =item 'u'
2975
2976 Unknown file type
2977
2978 =item '?'
2979
2980 The L<readdir(3)> returned a C<d_type> field with an
2981 unexpected value
2982
2983 =back
2984
2985 This function is primarily intended for use by programs.  To
2986 get a simple list of names, use C<guestfs_ls>.  To get a printable
2987 directory for human consumption, use C<guestfs_ll>.");
2988
2989   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2990    [],
2991    "create partitions on a block device",
2992    "\
2993 This is a simplified interface to the C<guestfs_sfdisk>
2994 command, where partition sizes are specified in megabytes
2995 only (rounded to the nearest cylinder) and you don't need
2996 to specify the cyls, heads and sectors parameters which
2997 were rarely if ever used anyway.
2998
2999 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3000
3001   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3002    [],
3003    "determine file type inside a compressed file",
3004    "\
3005 This command runs C<file> after first decompressing C<path>
3006 using C<method>.
3007
3008 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3009
3010 Since 1.0.63, use C<guestfs_file> instead which can now
3011 process compressed files.");
3012
3013   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3014    [],
3015    "list extended attributes of a file or directory",
3016    "\
3017 This call lists the extended attributes of the file or directory
3018 C<path>.
3019
3020 At the system call level, this is a combination of the
3021 L<listxattr(2)> and L<getxattr(2)> calls.
3022
3023 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3024
3025   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3026    [],
3027    "list extended attributes of a file or directory",
3028    "\
3029 This is the same as C<guestfs_getxattrs>, but if C<path>
3030 is a symbolic link, then it returns the extended attributes
3031 of the link itself.");
3032
3033   ("setxattr", (RErr, [String "xattr";
3034                        String "val"; Int "vallen"; (* will be BufferIn *)
3035                        Pathname "path"]), 143, [],
3036    [],
3037    "set extended attribute of a file or directory",
3038    "\
3039 This call sets the extended attribute named C<xattr>
3040 of the file C<path> to the value C<val> (of length C<vallen>).
3041 The value is arbitrary 8 bit data.
3042
3043 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3044
3045   ("lsetxattr", (RErr, [String "xattr";
3046                         String "val"; Int "vallen"; (* will be BufferIn *)
3047                         Pathname "path"]), 144, [],
3048    [],
3049    "set extended attribute of a file or directory",
3050    "\
3051 This is the same as C<guestfs_setxattr>, but if C<path>
3052 is a symbolic link, then it sets an extended attribute
3053 of the link itself.");
3054
3055   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3056    [],
3057    "remove extended attribute of a file or directory",
3058    "\
3059 This call removes the extended attribute named C<xattr>
3060 of the file C<path>.
3061
3062 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3063
3064   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3065    [],
3066    "remove extended attribute of a file or directory",
3067    "\
3068 This is the same as C<guestfs_removexattr>, but if C<path>
3069 is a symbolic link, then it removes an extended attribute
3070 of the link itself.");
3071
3072   ("mountpoints", (RHashtable "mps", []), 147, [],
3073    [],
3074    "show mountpoints",
3075    "\
3076 This call is similar to C<guestfs_mounts>.  That call returns
3077 a list of devices.  This one returns a hash table (map) of
3078 device name to directory where the device is mounted.");
3079
3080   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3081   (* This is a special case: while you would expect a parameter
3082    * of type "Pathname", that doesn't work, because it implies
3083    * NEED_ROOT in the generated calling code in stubs.c, and
3084    * this function cannot use NEED_ROOT.
3085    *)
3086    [],
3087    "create a mountpoint",
3088    "\
3089 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3090 specialized calls that can be used to create extra mountpoints
3091 before mounting the first filesystem.
3092
3093 These calls are I<only> necessary in some very limited circumstances,
3094 mainly the case where you want to mount a mix of unrelated and/or
3095 read-only filesystems together.
3096
3097 For example, live CDs often contain a \"Russian doll\" nest of
3098 filesystems, an ISO outer layer, with a squashfs image inside, with
3099 an ext2/3 image inside that.  You can unpack this as follows
3100 in guestfish:
3101
3102  add-ro Fedora-11-i686-Live.iso
3103  run
3104  mkmountpoint /cd
3105  mkmountpoint /squash
3106  mkmountpoint /ext3
3107  mount /dev/sda /cd
3108  mount-loop /cd/LiveOS/squashfs.img /squash
3109  mount-loop /squash/LiveOS/ext3fs.img /ext3
3110
3111 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3112
3113   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3114    [],
3115    "remove a mountpoint",
3116    "\
3117 This calls removes a mountpoint that was previously created
3118 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3119 for full details.");
3120
3121   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3122    [InitISOFS, Always, TestOutputBuffer (
3123       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3124    "read a file",
3125    "\
3126 This calls returns the contents of the file C<path> as a
3127 buffer.
3128
3129 Unlike C<guestfs_cat>, this function can correctly
3130 handle files that contain embedded ASCII NUL characters.
3131 However unlike C<guestfs_download>, this function is limited
3132 in the total size of file that can be handled.");
3133
3134   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3135    [InitISOFS, Always, TestOutputList (
3136       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3137     InitISOFS, Always, TestOutputList (
3138       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3139    "return lines matching a pattern",
3140    "\
3141 This calls the external C<grep> program and returns the
3142 matching lines.");
3143
3144   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3145    [InitISOFS, Always, TestOutputList (
3146       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3147    "return lines matching a pattern",
3148    "\
3149 This calls the external C<egrep> program and returns the
3150 matching lines.");
3151
3152   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3153    [InitISOFS, Always, TestOutputList (
3154       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3155    "return lines matching a pattern",
3156    "\
3157 This calls the external C<fgrep> program and returns the
3158 matching lines.");
3159
3160   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3161    [InitISOFS, Always, TestOutputList (
3162       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3163    "return lines matching a pattern",
3164    "\
3165 This calls the external C<grep -i> program and returns the
3166 matching lines.");
3167
3168   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3169    [InitISOFS, Always, TestOutputList (
3170       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3171    "return lines matching a pattern",
3172    "\
3173 This calls the external C<egrep -i> program and returns the
3174 matching lines.");
3175
3176   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3177    [InitISOFS, Always, TestOutputList (
3178       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3179    "return lines matching a pattern",
3180    "\
3181 This calls the external C<fgrep -i> program and returns the
3182 matching lines.");
3183
3184   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3185    [InitISOFS, Always, TestOutputList (
3186       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3187    "return lines matching a pattern",
3188    "\
3189 This calls the external C<zgrep> program and returns the
3190 matching lines.");
3191
3192   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3193    [InitISOFS, Always, TestOutputList (
3194       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3195    "return lines matching a pattern",
3196    "\
3197 This calls the external C<zegrep> program and returns the
3198 matching lines.");
3199
3200   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3201    [InitISOFS, Always, TestOutputList (
3202       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3203    "return lines matching a pattern",
3204    "\
3205 This calls the external C<zfgrep> program and returns the
3206 matching lines.");
3207
3208   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3209    [InitISOFS, Always, TestOutputList (
3210       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3211    "return lines matching a pattern",
3212    "\
3213 This calls the external C<zgrep -i> program and returns the
3214 matching lines.");
3215
3216   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3217    [InitISOFS, Always, TestOutputList (
3218       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3219    "return lines matching a pattern",
3220    "\
3221 This calls the external C<zegrep -i> program and returns the
3222 matching lines.");
3223
3224   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3225    [InitISOFS, Always, TestOutputList (
3226       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3227    "return lines matching a pattern",
3228    "\
3229 This calls the external C<zfgrep -i> program and returns the
3230 matching lines.");
3231
3232   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3233    [InitISOFS, Always, TestOutput (
3234       [["realpath"; "/../directory"]], "/directory")],
3235    "canonicalized absolute pathname",
3236    "\
3237 Return the canonicalized absolute pathname of C<path>.  The
3238 returned path has no C<.>, C<..> or symbolic link path elements.");
3239
3240   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3241    [InitBasicFS, Always, TestOutputStruct (
3242       [["touch"; "/a"];
3243        ["ln"; "/a"; "/b"];
3244        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3245    "create a hard link",
3246    "\
3247 This command creates a hard link using the C<ln> command.");
3248
3249   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3250    [InitBasicFS, Always, TestOutputStruct (
3251       [["touch"; "/a"];
3252        ["touch"; "/b"];
3253        ["ln_f"; "/a"; "/b"];
3254        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3255    "create a hard link",
3256    "\
3257 This command creates a hard link using the C<ln -f> command.
3258 The C<-f> option removes the link (C<linkname>) if it exists already.");
3259
3260   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3261    [InitBasicFS, Always, TestOutputStruct (
3262       [["touch"; "/a"];
3263        ["ln_s"; "a"; "/b"];
3264        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3265    "create a symbolic link",
3266    "\
3267 This command creates a symbolic link using the C<ln -s> command.");
3268
3269   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3270    [InitBasicFS, Always, TestOutput (
3271       [["mkdir_p"; "/a/b"];
3272        ["touch"; "/a/b/c"];
3273        ["ln_sf"; "../d"; "/a/b/c"];
3274        ["readlink"; "/a/b/c"]], "../d")],
3275    "create a symbolic link",
3276    "\
3277 This command creates a symbolic link using the C<ln -sf> command,
3278 The C<-f> option removes the link (C<linkname>) if it exists already.");
3279
3280   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3281    [] (* XXX tested above *),
3282    "read the target of a symbolic link",
3283    "\
3284 This command reads the target of a symbolic link.");
3285
3286   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["fallocate"; "/a"; "1000000"];
3289        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3290    "preallocate a file in the guest filesystem",
3291    "\
3292 This command preallocates a file (containing zero bytes) named
3293 C<path> of size C<len> bytes.  If the file exists already, it
3294 is overwritten.
3295
3296 Do not confuse this with the guestfish-specific
3297 C<alloc> command which allocates a file in the host and
3298 attaches it as a device.");
3299
3300   ("swapon_device", (RErr, [Device "device"]), 170, [],
3301    [InitPartition, Always, TestRun (
3302       [["mkswap"; "/dev/sda1"];
3303        ["swapon_device"; "/dev/sda1"];
3304        ["swapoff_device"; "/dev/sda1"]])],
3305    "enable swap on device",
3306    "\
3307 This command enables the libguestfs appliance to use the
3308 swap device or partition named C<device>.  The increased
3309 memory is made available for all commands, for example
3310 those run using C<guestfs_command> or C<guestfs_sh>.
3311
3312 Note that you should not swap to existing guest swap
3313 partitions unless you know what you are doing.  They may
3314 contain hibernation information, or other information that
3315 the guest doesn't want you to trash.  You also risk leaking
3316 information about the host to the guest this way.  Instead,
3317 attach a new host device to the guest and swap on that.");
3318
3319   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3320    [], (* XXX tested by swapon_device *)
3321    "disable swap on device",
3322    "\
3323 This command disables the libguestfs appliance swap
3324 device or partition named C<device>.
3325 See C<guestfs_swapon_device>.");
3326
3327   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3328    [InitBasicFS, Always, TestRun (
3329       [["fallocate"; "/swap"; "8388608"];
3330        ["mkswap_file"; "/swap"];
3331        ["swapon_file"; "/swap"];
3332        ["swapoff_file"; "/swap"]])],
3333    "enable swap on file",
3334    "\
3335 This command enables swap to a file.
3336 See C<guestfs_swapon_device> for other notes.");
3337
3338   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3339    [], (* XXX tested by swapon_file *)
3340    "disable swap on file",
3341    "\
3342 This command disables the libguestfs appliance swap on file.");
3343
3344   ("swapon_label", (RErr, [String "label"]), 174, [],
3345    [InitEmpty, Always, TestRun (
3346       [["sfdiskM"; "/dev/sdb"; ","];
3347        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3348        ["swapon_label"; "swapit"];
3349        ["swapoff_label"; "swapit"];
3350        ["zero"; "/dev/sdb"];
3351        ["blockdev_rereadpt"; "/dev/sdb"]])],
3352    "enable swap on labeled swap partition",
3353    "\
3354 This command enables swap to a labeled swap partition.
3355 See C<guestfs_swapon_device> for other notes.");
3356
3357   ("swapoff_label", (RErr, [String "label"]), 175, [],
3358    [], (* XXX tested by swapon_label *)
3359    "disable swap on labeled swap partition",
3360    "\
3361 This command disables the libguestfs appliance swap on
3362 labeled swap partition.");
3363
3364   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3365    (let uuid = uuidgen () in
3366     [InitEmpty, Always, TestRun (
3367        [["mkswap_U"; uuid; "/dev/sdb"];
3368         ["swapon_uuid"; uuid];
3369         ["swapoff_uuid"; uuid]])]),
3370    "enable swap on swap partition by UUID",
3371    "\
3372 This command enables swap to a swap partition with the given UUID.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3376    [], (* XXX tested by swapon_uuid *)
3377    "disable swap on swap partition by UUID",
3378    "\
3379 This command disables the libguestfs appliance swap partition
3380 with the given UUID.");
3381
3382   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3383    [InitBasicFS, Always, TestRun (
3384       [["fallocate"; "/swap"; "8388608"];
3385        ["mkswap_file"; "/swap"]])],
3386    "create a swap file",
3387    "\
3388 Create a swap file.
3389
3390 This command just writes a swap file signature to an existing
3391 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3392
3393   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3394    [InitISOFS, Always, TestRun (
3395       [["inotify_init"; "0"]])],
3396    "create an inotify handle",
3397    "\
3398 This command creates a new inotify handle.
3399 The inotify subsystem can be used to notify events which happen to
3400 objects in the guest filesystem.
3401
3402 C<maxevents> is the maximum number of events which will be
3403 queued up between calls to C<guestfs_inotify_read> or
3404 C<guestfs_inotify_files>.
3405 If this is passed as C<0>, then the kernel (or previously set)
3406 default is used.  For Linux 2.6.29 the default was 16384 events.
3407 Beyond this limit, the kernel throws away events, but records
3408 the fact that it threw them away by setting a flag
3409 C<IN_Q_OVERFLOW> in the returned structure list (see
3410 C<guestfs_inotify_read>).
3411
3412 Before any events are generated, you have to add some
3413 watches to the internal watch list.  See:
3414 C<guestfs_inotify_add_watch>,
3415 C<guestfs_inotify_rm_watch> and
3416 C<guestfs_inotify_watch_all>.
3417
3418 Queued up events should be read periodically by calling
3419 C<guestfs_inotify_read>
3420 (or C<guestfs_inotify_files> which is just a helpful
3421 wrapper around C<guestfs_inotify_read>).  If you don't
3422 read the events out often enough then you risk the internal
3423 queue overflowing.
3424
3425 The handle should be closed after use by calling
3426 C<guestfs_inotify_close>.  This also removes any
3427 watches automatically.
3428
3429 See also L<inotify(7)> for an overview of the inotify interface
3430 as exposed by the Linux kernel, which is roughly what we expose
3431 via libguestfs.  Note that there is one global inotify handle
3432 per libguestfs instance.");
3433
3434   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3435    [InitBasicFS, Always, TestOutputList (
3436       [["inotify_init"; "0"];
3437        ["inotify_add_watch"; "/"; "1073741823"];
3438        ["touch"; "/a"];
3439        ["touch"; "/b"];
3440        ["inotify_files"]], ["a"; "b"])],
3441    "add an inotify watch",
3442    "\
3443 Watch C<path> for the events listed in C<mask>.
3444
3445 Note that if C<path> is a directory then events within that
3446 directory are watched, but this does I<not> happen recursively
3447 (in subdirectories).
3448
3449 Note for non-C or non-Linux callers: the inotify events are
3450 defined by the Linux kernel ABI and are listed in
3451 C</usr/include/sys/inotify.h>.");
3452
3453   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3454    [],
3455    "remove an inotify watch",
3456    "\
3457 Remove a previously defined inotify watch.
3458 See C<guestfs_inotify_add_watch>.");
3459
3460   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3461    [],
3462    "return list of inotify events",
3463    "\
3464 Return the complete queue of events that have happened
3465 since the previous read call.
3466
3467 If no events have happened, this returns an empty list.
3468
3469 I<Note>: In order to make sure that all events have been
3470 read, you must call this function repeatedly until it
3471 returns an empty list.  The reason is that the call will
3472 read events up to the maximum appliance-to-host message
3473 size and leave remaining events in the queue.");
3474
3475   ("inotify_files", (RStringList "paths", []), 183, [],
3476    [],
3477    "return list of watched files that had events",
3478    "\
3479 This function is a helpful wrapper around C<guestfs_inotify_read>
3480 which just returns a list of pathnames of objects that were
3481 touched.  The returned pathnames are sorted and deduplicated.");
3482
3483   ("inotify_close", (RErr, []), 184, [],
3484    [],
3485    "close the inotify handle",
3486    "\
3487 This closes the inotify handle which was previously
3488 opened by inotify_init.  It removes all watches, throws
3489 away any pending events, and deallocates all resources.");
3490
3491   ("setcon", (RErr, [String "context"]), 185, [],
3492    [],
3493    "set SELinux security context",
3494    "\
3495 This sets the SELinux security context of the daemon
3496 to the string C<context>.
3497
3498 See the documentation about SELINUX in L<guestfs(3)>.");
3499
3500   ("getcon", (RString "context", []), 186, [],
3501    [],
3502    "get SELinux security context",
3503    "\
3504 This gets the SELinux security context of the daemon.
3505
3506 See the documentation about SELINUX in L<guestfs(3)>,
3507 and C<guestfs_setcon>");
3508
3509   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3510    [InitEmpty, Always, TestOutput (
3511       [["sfdiskM"; "/dev/sda"; ","];
3512        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3513        ["mount"; "/dev/sda1"; "/"];
3514        ["write_file"; "/new"; "new file contents"; "0"];
3515        ["cat"; "/new"]], "new file contents")],
3516    "make a filesystem with block size",
3517    "\
3518 This call is similar to C<guestfs_mkfs>, but it allows you to
3519 control the block size of the resulting filesystem.  Supported
3520 block sizes depend on the filesystem type, but typically they
3521 are C<1024>, C<2048> or C<4096> only.");
3522
3523   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3524    [InitEmpty, Always, TestOutput (
3525       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3526        ["mke2journal"; "4096"; "/dev/sda1"];
3527        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3528        ["mount"; "/dev/sda2"; "/"];
3529        ["write_file"; "/new"; "new file contents"; "0"];
3530        ["cat"; "/new"]], "new file contents")],
3531    "make ext2/3/4 external journal",
3532    "\
3533 This creates an ext2 external journal on C<device>.  It is equivalent
3534 to the command:
3535
3536  mke2fs -O journal_dev -b blocksize device");
3537
3538   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3539    [InitEmpty, Always, TestOutput (
3540       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3541        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3542        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3543        ["mount"; "/dev/sda2"; "/"];
3544        ["write_file"; "/new"; "new file contents"; "0"];
3545        ["cat"; "/new"]], "new file contents")],
3546    "make ext2/3/4 external journal with label",
3547    "\
3548 This creates an ext2 external journal on C<device> with label C<label>.");
3549
3550   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3551    (let uuid = uuidgen () in
3552     [InitEmpty, Always, TestOutput (
3553        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3554         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3555         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3556         ["mount"; "/dev/sda2"; "/"];
3557         ["write_file"; "/new"; "new file contents"; "0"];
3558         ["cat"; "/new"]], "new file contents")]),
3559    "make ext2/3/4 external journal with UUID",
3560    "\
3561 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3562
3563   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3564    [],
3565    "make ext2/3/4 filesystem with external journal",
3566    "\
3567 This creates an ext2/3/4 filesystem on C<device> with
3568 an external journal on C<journal>.  It is equivalent
3569 to the command:
3570
3571  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3572
3573 See also C<guestfs_mke2journal>.");
3574
3575   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3576    [],
3577    "make ext2/3/4 filesystem with external journal",
3578    "\
3579 This creates an ext2/3/4 filesystem on C<device> with
3580 an external journal on the journal labeled C<label>.
3581
3582 See also C<guestfs_mke2journal_L>.");
3583
3584   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3585    [],
3586    "make ext2/3/4 filesystem with external journal",
3587    "\
3588 This creates an ext2/3/4 filesystem on C<device> with
3589 an external journal on the journal with UUID C<uuid>.
3590
3591 See also C<guestfs_mke2journal_U>.");
3592
3593   ("modprobe", (RErr, [String "modulename"]), 194, [],
3594    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3595    "load a kernel module",
3596    "\
3597 This loads a kernel module in the appliance.
3598
3599 The kernel module must have been whitelisted when libguestfs
3600 was built (see C<appliance/kmod.whitelist.in> in the source).");
3601
3602   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3603    [InitNone, Always, TestOutput (
3604      [["echo_daemon"; "This is a test"]], "This is a test"
3605    )],
3606    "echo arguments back to the client",
3607    "\
3608 This command concatenate the list of C<words> passed with single spaces between
3609 them and returns the resulting string.
3610
3611 You can use this command to test the connection through to the daemon.
3612
3613 See also C<guestfs_ping_daemon>.");
3614
3615   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3616    [], (* There is a regression test for this. *)
3617    "find all files and directories, returning NUL-separated list",
3618    "\
3619 This command lists out all files and directories, recursively,
3620 starting at C<directory>, placing the resulting list in the
3621 external file called C<files>.
3622
3623 This command works the same way as C<guestfs_find> with the
3624 following exceptions:
3625
3626 =over 4
3627
3628 =item *
3629
3630 The resulting list is written to an external file.
3631
3632 =item *
3633
3634 Items (filenames) in the result are separated
3635 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3636
3637 =item *
3638
3639 This command is not limited in the number of names that it
3640 can return.
3641
3642 =item *
3643
3644 The result list is not sorted.
3645
3646 =back");
3647
3648   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3649    [InitISOFS, Always, TestOutput (
3650       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3651     InitISOFS, Always, TestOutput (
3652       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3653     InitISOFS, Always, TestOutput (
3654       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3655     InitISOFS, Always, TestLastFail (
3656       [["case_sensitive_path"; "/Known-1/"]]);
3657     InitBasicFS, Always, TestOutput (
3658       [["mkdir"; "/a"];
3659        ["mkdir"; "/a/bbb"];
3660        ["touch"; "/a/bbb/c"];
3661        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3662     InitBasicFS, Always, TestOutput (
3663       [["mkdir"; "/a"];
3664        ["mkdir"; "/a/bbb"];
3665        ["touch"; "/a/bbb/c"];
3666        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3667     InitBasicFS, Always, TestLastFail (
3668       [["mkdir"; "/a"];
3669        ["mkdir"; "/a/bbb"];
3670        ["touch"; "/a/bbb/c"];
3671        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3672    "return true path on case-insensitive filesystem",
3673    "\
3674 This can be used to resolve case insensitive paths on
3675 a filesystem which is case sensitive.  The use case is
3676 to resolve paths which you have read from Windows configuration
3677 files or the Windows Registry, to the true path.
3678
3679 The command handles a peculiarity of the Linux ntfs-3g
3680 filesystem driver (and probably others), which is that although
3681 the underlying filesystem is case-insensitive, the driver
3682 exports the filesystem to Linux as case-sensitive.
3683
3684 One consequence of this is that special directories such
3685 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3686 (or other things) depending on the precise details of how
3687 they were created.  In Windows itself this would not be
3688 a problem.
3689
3690 Bug or feature?  You decide:
3691 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3692
3693 This function resolves the true case of each element in the
3694 path and returns the case-sensitive path.
3695
3696 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3697 might return C<\"/WINDOWS/system32\"> (the exact return value
3698 would depend on details of how the directories were originally
3699 created under Windows).
3700
3701 I<Note>:
3702 This function does not handle drive names, backslashes etc.
3703
3704 See also C<guestfs_realpath>.");
3705
3706 ]
3707
3708 let all_functions = non_daemon_functions @ daemon_functions
3709
3710 (* In some places we want the functions to be displayed sorted
3711  * alphabetically, so this is useful:
3712  *)
3713 let all_functions_sorted =
3714   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3715                compare n1 n2) all_functions
3716
3717 (* Field types for structures. *)
3718 type field =
3719   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3720   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3721   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3722   | FUInt32
3723   | FInt32
3724   | FUInt64
3725   | FInt64
3726   | FBytes                      (* Any int measure that counts bytes. *)
3727   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3728   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3729
3730 (* Because we generate extra parsing code for LVM command line tools,
3731  * we have to pull out the LVM columns separately here.
3732  *)
3733 let lvm_pv_cols = [
3734   "pv_name", FString;
3735   "pv_uuid", FUUID;
3736   "pv_fmt", FString;
3737   "pv_size", FBytes;
3738   "dev_size", FBytes;
3739   "pv_free", FBytes;
3740   "pv_used", FBytes;
3741   "pv_attr", FString (* XXX *);
3742   "pv_pe_count", FInt64;
3743   "pv_pe_alloc_count", FInt64;
3744   "pv_tags", FString;
3745   "pe_start", FBytes;
3746   "pv_mda_count", FInt64;
3747   "pv_mda_free", FBytes;
3748   (* Not in Fedora 10:
3749      "pv_mda_size", FBytes;
3750   *)
3751 ]
3752 let lvm_vg_cols = [
3753   "vg_name", FString;
3754   "vg_uuid", FUUID;
3755   "vg_fmt", FString;
3756   "vg_attr", FString (* XXX *);
3757   "vg_size", FBytes;
3758   "vg_free", FBytes;
3759   "vg_sysid", FString;
3760   "vg_extent_size", FBytes;
3761   "vg_extent_count", FInt64;
3762   "vg_free_count", FInt64;
3763   "max_lv", FInt64;
3764   "max_pv", FInt64;
3765   "pv_count", FInt64;
3766   "lv_count", FInt64;
3767   "snap_count", FInt64;
3768   "vg_seqno", FInt64;
3769   "vg_tags", FString;
3770   "vg_mda_count", FInt64;
3771   "vg_mda_free", FBytes;
3772   (* Not in Fedora 10:
3773      "vg_mda_size", FBytes;
3774   *)
3775 ]
3776 let lvm_lv_cols = [
3777   "lv_name", FString;
3778   "lv_uuid", FUUID;
3779   "lv_attr", FString (* XXX *);
3780   "lv_major", FInt64;
3781   "lv_minor", FInt64;
3782   "lv_kernel_major", FInt64;
3783   "lv_kernel_minor", FInt64;
3784   "lv_size", FBytes;
3785   "seg_count", FInt64;
3786   "origin", FString;
3787   "snap_percent", FOptPercent;
3788   "copy_percent", FOptPercent;
3789   "move_pv", FString;
3790   "lv_tags", FString;
3791   "mirror_log", FString;
3792   "modules", FString;
3793 ]
3794
3795 (* Names and fields in all structures (in RStruct and RStructList)
3796  * that we support.
3797  *)
3798 let structs = [
3799   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3800    * not use this struct in any new code.
3801    *)
3802   "int_bool", [
3803     "i", FInt32;                (* for historical compatibility *)
3804     "b", FInt32;                (* for historical compatibility *)
3805   ];
3806
3807   (* LVM PVs, VGs, LVs. *)
3808   "lvm_pv", lvm_pv_cols;
3809   "lvm_vg", lvm_vg_cols;
3810   "lvm_lv", lvm_lv_cols;
3811
3812   (* Column names and types from stat structures.
3813    * NB. Can't use things like 'st_atime' because glibc header files
3814    * define some of these as macros.  Ugh.
3815    *)
3816   "stat", [
3817     "dev", FInt64;
3818     "ino", FInt64;
3819     "mode", FInt64;
3820     "nlink", FInt64;
3821     "uid", FInt64;
3822     "gid", FInt64;
3823     "rdev", FInt64;
3824     "size", FInt64;
3825     "blksize", FInt64;
3826     "blocks", FInt64;
3827     "atime", FInt64;
3828     "mtime", FInt64;
3829     "ctime", FInt64;
3830   ];
3831   "statvfs", [
3832     "bsize", FInt64;
3833     "frsize", FInt64;
3834     "blocks", FInt64;
3835     "bfree", FInt64;
3836     "bavail", FInt64;
3837     "files", FInt64;
3838     "ffree", FInt64;
3839     "favail", FInt64;
3840     "fsid", FInt64;
3841     "flag", FInt64;
3842     "namemax", FInt64;
3843   ];
3844
3845   (* Column names in dirent structure. *)
3846   "dirent", [
3847     "ino", FInt64;
3848     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3849     "ftyp", FChar;
3850     "name", FString;
3851   ];
3852
3853   (* Version numbers. *)
3854   "version", [
3855     "major", FInt64;
3856     "minor", FInt64;
3857     "release", FInt64;
3858     "extra", FString;
3859   ];
3860
3861   (* Extended attribute. *)
3862   "xattr", [
3863     "attrname", FString;
3864     "attrval", FBuffer;
3865   ];
3866
3867   (* Inotify events. *)
3868   "inotify_event", [
3869     "in_wd", FInt64;
3870     "in_mask", FUInt32;
3871     "in_cookie", FUInt32;
3872     "in_name", FString;
3873   ];
3874 ] (* end of structs *)
3875
3876 (* Ugh, Java has to be different ..
3877  * These names are also used by the Haskell bindings.
3878  *)
3879 let java_structs = [
3880   "int_bool", "IntBool";
3881   "lvm_pv", "PV";
3882   "lvm_vg", "VG";
3883   "lvm_lv", "LV";
3884   "stat", "Stat";
3885   "statvfs", "StatVFS";
3886   "dirent", "Dirent";
3887   "version", "Version";
3888   "xattr", "XAttr";
3889   "inotify_event", "INotifyEvent";
3890 ]
3891
3892 (* What structs are actually returned. *)
3893 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3894
3895 (* Returns a list of RStruct/RStructList structs that are returned
3896  * by any function.  Each element of returned list is a pair:
3897  *
3898  * (structname, RStructOnly)
3899  *    == there exists function which returns RStruct (_, structname)
3900  * (structname, RStructListOnly)
3901  *    == there exists function which returns RStructList (_, structname)
3902  * (structname, RStructAndList)
3903  *    == there are functions returning both RStruct (_, structname)
3904  *                                      and RStructList (_, structname)
3905  *)
3906 let rstructs_used =
3907   (* ||| is a "logical OR" for rstructs_used_t *)
3908   let (|||) a b =
3909     match a, b with
3910     | RStructAndList, _
3911     | _, RStructAndList -> RStructAndList
3912     | RStructOnly, RStructListOnly
3913     | RStructListOnly, RStructOnly -> RStructAndList
3914     | RStructOnly, RStructOnly -> RStructOnly
3915     | RStructListOnly, RStructListOnly -> RStructListOnly
3916   in
3917
3918   let h = Hashtbl.create 13 in
3919
3920   (* if elem->oldv exists, update entry using ||| operator,
3921    * else just add elem->newv to the hash
3922    *)
3923   let update elem newv =
3924     try  let oldv = Hashtbl.find h elem in
3925          Hashtbl.replace h elem (newv ||| oldv)
3926     with Not_found -> Hashtbl.add h elem newv
3927   in
3928
3929   List.iter (
3930     fun (_, style, _, _, _, _, _) ->
3931       match fst style with
3932       | RStruct (_, structname) -> update structname RStructOnly
3933       | RStructList (_, structname) -> update structname RStructListOnly
3934       | _ -> ()
3935   ) all_functions;
3936
3937   (* return key->values as a list of (key,value) *)
3938   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3939
3940 (* debug:
3941 let () =
3942   List.iter (
3943     function
3944     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3945     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3946     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3947   ) rstructs_used
3948 *)
3949
3950 (* Used for testing language bindings. *)
3951 type callt =
3952   | CallString of string
3953   | CallOptString of string option
3954   | CallStringList of string list
3955   | CallInt of int
3956   | CallBool of bool
3957
3958 (* Used to memoize the result of pod2text. *)
3959 let pod2text_memo_filename = "src/.pod2text.data"
3960 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3961   try
3962     let chan = open_in pod2text_memo_filename in
3963     let v = input_value chan in
3964     close_in chan;
3965     v
3966   with
3967     _ -> Hashtbl.create 13
3968 let pod2text_memo_updated () =
3969   let chan = open_out pod2text_memo_filename in
3970   output_value chan pod2text_memo;
3971   close_out chan
3972
3973 (* Useful functions.
3974  * Note we don't want to use any external OCaml libraries which
3975  * makes this a bit harder than it should be.
3976  *)
3977 let failwithf fs = ksprintf failwith fs
3978
3979 let replace_char s c1 c2 =
3980   let s2 = String.copy s in
3981   let r = ref false in
3982   for i = 0 to String.length s2 - 1 do
3983     if String.unsafe_get s2 i = c1 then (
3984       String.unsafe_set s2 i c2;
3985       r := true
3986     )
3987   done;
3988   if not !r then s else s2
3989
3990 let isspace c =
3991   c = ' '
3992   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3993
3994 let triml ?(test = isspace) str =
3995   let i = ref 0 in
3996   let n = ref (String.length str) in
3997   while !n > 0 && test str.[!i]; do
3998     decr n;
3999     incr i
4000   done;
4001   if !i = 0 then str
4002   else String.sub str !i !n
4003
4004 let trimr ?(test = isspace) str =
4005   let n = ref (String.length str) in
4006   while !n > 0 && test str.[!n-1]; do
4007     decr n
4008   done;
4009   if !n = String.length str then str
4010   else String.sub str 0 !n
4011
4012 let trim ?(test = isspace) str =
4013   trimr ~test (triml ~test str)
4014
4015 let rec find s sub =
4016   let len = String.length s in
4017   let sublen = String.length sub in
4018   let rec loop i =
4019     if i <= len-sublen then (
4020       let rec loop2 j =
4021         if j < sublen then (
4022           if s.[i+j] = sub.[j] then loop2 (j+1)
4023           else -1
4024         ) else
4025           i (* found *)
4026       in
4027       let r = loop2 0 in
4028       if r = -1 then loop (i+1) else r
4029     ) else
4030       -1 (* not found *)
4031   in
4032   loop 0
4033
4034 let rec replace_str s s1 s2 =
4035   let len = String.length s in
4036   let sublen = String.length s1 in
4037   let i = find s s1 in
4038   if i = -1 then s
4039   else (
4040     let s' = String.sub s 0 i in
4041     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4042     s' ^ s2 ^ replace_str s'' s1 s2
4043   )
4044
4045 let rec string_split sep str =
4046   let len = String.length str in
4047   let seplen = String.length sep in
4048   let i = find str sep in
4049   if i = -1 then [str]
4050   else (
4051     let s' = String.sub str 0 i in
4052     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4053     s' :: string_split sep s''
4054   )
4055
4056 let files_equal n1 n2 =
4057   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4058   match Sys.command cmd with
4059   | 0 -> true
4060   | 1 -> false
4061   | i -> failwithf "%s: failed with error code %d" cmd i
4062
4063 let rec filter_map f = function
4064   | [] -> []
4065   | x :: xs ->
4066       match f x with
4067       | Some y -> y :: filter_map f xs
4068       | None -> filter_map f xs
4069
4070 let rec find_map f = function
4071   | [] -> raise Not_found
4072   | x :: xs ->
4073       match f x with
4074       | Some y -> y
4075       | None -> find_map f xs
4076
4077 let iteri f xs =
4078   let rec loop i = function
4079     | [] -> ()
4080     | x :: xs -> f i x; loop (i+1) xs
4081   in
4082   loop 0 xs
4083
4084 let mapi f xs =
4085   let rec loop i = function
4086     | [] -> []
4087     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4088   in
4089   loop 0 xs
4090
4091 let name_of_argt = function
4092   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4093   | StringList n | DeviceList n | Bool n | Int n
4094   | FileIn n | FileOut n -> n
4095
4096 let java_name_of_struct typ =
4097   try List.assoc typ java_structs
4098   with Not_found ->
4099     failwithf
4100       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4101
4102 let cols_of_struct typ =
4103   try List.assoc typ structs
4104   with Not_found ->
4105     failwithf "cols_of_struct: unknown struct %s" typ
4106
4107 let seq_of_test = function
4108   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4109   | TestOutputListOfDevices (s, _)
4110   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4111   | TestOutputTrue s | TestOutputFalse s
4112   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4113   | TestOutputStruct (s, _)
4114   | TestLastFail s -> s
4115
4116 (* Handling for function flags. *)
4117 let protocol_limit_warning =
4118   "Because of the message protocol, there is a transfer limit
4119 of somewhere between 2MB and 4MB.  To transfer large files you should use
4120 FTP."
4121
4122 let danger_will_robinson =
4123   "B<This command is dangerous.  Without careful use you
4124 can easily destroy all your data>."
4125
4126 let deprecation_notice flags =
4127   try
4128     let alt =
4129       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4130     let txt =
4131       sprintf "This function is deprecated.
4132 In new code, use the C<%s> call instead.
4133
4134 Deprecated functions will not be removed from the API, but the
4135 fact that they are deprecated indicates that there are problems
4136 with correct use of these functions." alt in
4137     Some txt
4138   with
4139     Not_found -> None
4140
4141 (* Check function names etc. for consistency. *)
4142 let check_functions () =
4143   let contains_uppercase str =
4144     let len = String.length str in
4145     let rec loop i =
4146       if i >= len then false
4147       else (
4148         let c = str.[i] in
4149         if c >= 'A' && c <= 'Z' then true
4150         else loop (i+1)
4151       )
4152     in
4153     loop 0
4154   in
4155
4156   (* Check function names. *)
4157   List.iter (
4158     fun (name, _, _, _, _, _, _) ->
4159       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4160         failwithf "function name %s does not need 'guestfs' prefix" name;
4161       if name = "" then
4162         failwithf "function name is empty";
4163       if name.[0] < 'a' || name.[0] > 'z' then
4164         failwithf "function name %s must start with lowercase a-z" name;
4165       if String.contains name '-' then
4166         failwithf "function name %s should not contain '-', use '_' instead."
4167           name
4168   ) all_functions;
4169
4170   (* Check function parameter/return names. *)
4171   List.iter (
4172     fun (name, style, _, _, _, _, _) ->
4173       let check_arg_ret_name n =
4174         if contains_uppercase n then
4175           failwithf "%s param/ret %s should not contain uppercase chars"
4176             name n;
4177         if String.contains n '-' || String.contains n '_' then
4178           failwithf "%s param/ret %s should not contain '-' or '_'"
4179             name n;
4180         if n = "value" then
4181           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;
4182         if n = "int" || n = "char" || n = "short" || n = "long" then
4183           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4184         if n = "i" || n = "n" then
4185           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4186         if n = "argv" || n = "args" then
4187           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4188
4189         (* List Haskell, OCaml and C keywords here.
4190          * http://www.haskell.org/haskellwiki/Keywords
4191          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4192          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4193          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4194          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4195          * Omitting _-containing words, since they're handled above.
4196          * Omitting the OCaml reserved word, "val", is ok,
4197          * and saves us from renaming several parameters.
4198          *)
4199         let reserved = [
4200           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4201           "char"; "class"; "const"; "constraint"; "continue"; "data";
4202           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4203           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4204           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4205           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4206           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4207           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4208           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4209           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4210           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4211           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4212           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4213           "volatile"; "when"; "where"; "while";
4214           ] in
4215         if List.mem n reserved then
4216           failwithf "%s has param/ret using reserved word %s" name n;
4217       in
4218
4219       (match fst style with
4220        | RErr -> ()
4221        | RInt n | RInt64 n | RBool n
4222        | RConstString n | RConstOptString n | RString n
4223        | RStringList n | RStruct (n, _) | RStructList (n, _)
4224        | RHashtable n | RBufferOut n ->
4225            check_arg_ret_name n
4226       );
4227       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4228   ) all_functions;
4229
4230   (* Check short descriptions. *)
4231   List.iter (
4232     fun (name, _, _, _, _, shortdesc, _) ->
4233       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4234         failwithf "short description of %s should begin with lowercase." name;
4235       let c = shortdesc.[String.length shortdesc-1] in
4236       if c = '\n' || c = '.' then
4237         failwithf "short description of %s should not end with . or \\n." name
4238   ) all_functions;
4239
4240   (* Check long dscriptions. *)
4241   List.iter (
4242     fun (name, _, _, _, _, _, longdesc) ->
4243       if longdesc.[String.length longdesc-1] = '\n' then
4244         failwithf "long description of %s should not end with \\n." name
4245   ) all_functions;
4246
4247   (* Check proc_nrs. *)
4248   List.iter (
4249     fun (name, _, proc_nr, _, _, _, _) ->
4250       if proc_nr <= 0 then
4251         failwithf "daemon function %s should have proc_nr > 0" name
4252   ) daemon_functions;
4253
4254   List.iter (
4255     fun (name, _, proc_nr, _, _, _, _) ->
4256       if proc_nr <> -1 then
4257         failwithf "non-daemon function %s should have proc_nr -1" name
4258   ) non_daemon_functions;
4259
4260   let proc_nrs =
4261     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4262       daemon_functions in
4263   let proc_nrs =
4264     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4265   let rec loop = function
4266     | [] -> ()
4267     | [_] -> ()
4268     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4269         loop rest
4270     | (name1,nr1) :: (name2,nr2) :: _ ->
4271         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4272           name1 name2 nr1 nr2
4273   in
4274   loop proc_nrs;
4275
4276   (* Check tests. *)
4277   List.iter (
4278     function
4279       (* Ignore functions that have no tests.  We generate a
4280        * warning when the user does 'make check' instead.
4281        *)
4282     | name, _, _, _, [], _, _ -> ()
4283     | name, _, _, _, tests, _, _ ->
4284         let funcs =
4285           List.map (
4286             fun (_, _, test) ->
4287               match seq_of_test test with
4288               | [] ->
4289                   failwithf "%s has a test containing an empty sequence" name
4290               | cmds -> List.map List.hd cmds
4291           ) tests in
4292         let funcs = List.flatten funcs in
4293
4294         let tested = List.mem name funcs in
4295
4296         if not tested then
4297           failwithf "function %s has tests but does not test itself" name
4298   ) all_functions
4299
4300 (* 'pr' prints to the current output file. *)
4301 let chan = ref stdout
4302 let pr fs = ksprintf (output_string !chan) fs
4303
4304 (* Generate a header block in a number of standard styles. *)
4305 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4306 type license = GPLv2 | LGPLv2
4307
4308 let generate_header comment license =
4309   let c = match comment with
4310     | CStyle ->     pr "/* "; " *"
4311     | HashStyle ->  pr "# ";  "#"
4312     | OCamlStyle -> pr "(* "; " *"
4313     | HaskellStyle -> pr "{- "; "  " in
4314   pr "libguestfs generated file\n";
4315   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4316   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4317   pr "%s\n" c;
4318   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4319   pr "%s\n" c;
4320   (match license with
4321    | GPLv2 ->
4322        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4323        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4324        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4325        pr "%s (at your option) any later version.\n" c;
4326        pr "%s\n" c;
4327        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4328        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4329        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4330        pr "%s GNU General Public License for more details.\n" c;
4331        pr "%s\n" c;
4332        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4333        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4334        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4335
4336    | LGPLv2 ->
4337        pr "%s This library is free software; you can redistribute it and/or\n" c;
4338        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4339        pr "%s License as published by the Free Software Foundation; either\n" c;
4340        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4341        pr "%s\n" c;
4342        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4343        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4344        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4345        pr "%s Lesser General Public License for more details.\n" c;
4346        pr "%s\n" c;
4347        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4348        pr "%s License along with this library; if not, write to the Free Software\n" c;
4349        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4350   );
4351   (match comment with
4352    | CStyle -> pr " */\n"
4353    | HashStyle -> ()
4354    | OCamlStyle -> pr " *)\n"
4355    | HaskellStyle -> pr "-}\n"
4356   );
4357   pr "\n"
4358
4359 (* Start of main code generation functions below this line. *)
4360
4361 (* Generate the pod documentation for the C API. *)
4362 let rec generate_actions_pod () =
4363   List.iter (
4364     fun (shortname, style, _, flags, _, _, longdesc) ->
4365       if not (List.mem NotInDocs flags) then (
4366         let name = "guestfs_" ^ shortname in
4367         pr "=head2 %s\n\n" name;
4368         pr " ";
4369         generate_prototype ~extern:false ~handle:"handle" name style;
4370         pr "\n\n";
4371         pr "%s\n\n" longdesc;
4372         (match fst style with
4373          | RErr ->
4374              pr "This function returns 0 on success or -1 on error.\n\n"
4375          | RInt _ ->
4376              pr "On error this function returns -1.\n\n"
4377          | RInt64 _ ->
4378              pr "On error this function returns -1.\n\n"
4379          | RBool _ ->
4380              pr "This function returns a C truth value on success or -1 on error.\n\n"
4381          | RConstString _ ->
4382              pr "This function returns a string, or NULL on error.
4383 The string is owned by the guest handle and must I<not> be freed.\n\n"
4384          | RConstOptString _ ->
4385              pr "This function returns a string which may be NULL.
4386 There is way to return an error from this function.
4387 The string is owned by the guest handle and must I<not> be freed.\n\n"
4388          | RString _ ->
4389              pr "This function returns a string, or NULL on error.
4390 I<The caller must free the returned string after use>.\n\n"
4391          | RStringList _ ->
4392              pr "This function returns a NULL-terminated array of strings
4393 (like L<environ(3)>), or NULL if there was an error.
4394 I<The caller must free the strings and the array after use>.\n\n"
4395          | RStruct (_, typ) ->
4396              pr "This function returns a C<struct guestfs_%s *>,
4397 or NULL if there was an error.
4398 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4399          | RStructList (_, typ) ->
4400              pr "This function returns a C<struct guestfs_%s_list *>
4401 (see E<lt>guestfs-structs.hE<gt>),
4402 or NULL if there was an error.
4403 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4404          | RHashtable _ ->
4405              pr "This function returns a NULL-terminated array of
4406 strings, or NULL if there was an error.
4407 The array of strings will always have length C<2n+1>, where
4408 C<n> keys and values alternate, followed by the trailing NULL entry.
4409 I<The caller must free the strings and the array after use>.\n\n"
4410          | RBufferOut _ ->
4411              pr "This function returns a buffer, or NULL on error.
4412 The size of the returned buffer is written to C<*size_r>.
4413 I<The caller must free the returned buffer after use>.\n\n"
4414         );
4415         if List.mem ProtocolLimitWarning flags then
4416           pr "%s\n\n" protocol_limit_warning;
4417         if List.mem DangerWillRobinson flags then
4418           pr "%s\n\n" danger_will_robinson;
4419         match deprecation_notice flags with
4420         | None -> ()
4421         | Some txt -> pr "%s\n\n" txt
4422       )
4423   ) all_functions_sorted
4424
4425 and generate_structs_pod () =
4426   (* Structs documentation. *)
4427   List.iter (
4428     fun (typ, cols) ->
4429       pr "=head2 guestfs_%s\n" typ;
4430       pr "\n";
4431       pr " struct guestfs_%s {\n" typ;
4432       List.iter (
4433         function
4434         | name, FChar -> pr "   char %s;\n" name
4435         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4436         | name, FInt32 -> pr "   int32_t %s;\n" name
4437         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4438         | name, FInt64 -> pr "   int64_t %s;\n" name
4439         | name, FString -> pr "   char *%s;\n" name
4440         | name, FBuffer ->
4441             pr "   /* The next two fields describe a byte array. */\n";
4442             pr "   uint32_t %s_len;\n" name;
4443             pr "   char *%s;\n" name
4444         | name, FUUID ->
4445             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4446             pr "   char %s[32];\n" name
4447         | name, FOptPercent ->
4448             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4449             pr "   float %s;\n" name
4450       ) cols;
4451       pr " };\n";
4452       pr " \n";
4453       pr " struct guestfs_%s_list {\n" typ;
4454       pr "   uint32_t len; /* Number of elements in list. */\n";
4455       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4456       pr " };\n";
4457       pr " \n";
4458       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4459       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4460         typ typ;
4461       pr "\n"
4462   ) structs
4463
4464 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4465  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4466  *
4467  * We have to use an underscore instead of a dash because otherwise
4468  * rpcgen generates incorrect code.
4469  *
4470  * This header is NOT exported to clients, but see also generate_structs_h.
4471  *)
4472 and generate_xdr () =
4473   generate_header CStyle LGPLv2;
4474
4475   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4476   pr "typedef string str<>;\n";
4477   pr "\n";
4478
4479   (* Internal structures. *)
4480   List.iter (
4481     function
4482     | typ, cols ->
4483         pr "struct guestfs_int_%s {\n" typ;
4484         List.iter (function
4485                    | name, FChar -> pr "  char %s;\n" name
4486                    | name, FString -> pr "  string %s<>;\n" name
4487                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4488                    | name, FUUID -> pr "  opaque %s[32];\n" name
4489                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4490                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4491                    | name, FOptPercent -> pr "  float %s;\n" name
4492                   ) cols;
4493         pr "};\n";
4494         pr "\n";
4495         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4496         pr "\n";
4497   ) structs;
4498
4499   List.iter (
4500     fun (shortname, style, _, _, _, _, _) ->
4501       let name = "guestfs_" ^ shortname in
4502
4503       (match snd style with
4504        | [] -> ()
4505        | args ->
4506            pr "struct %s_args {\n" name;
4507            List.iter (
4508              function
4509              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4510              | OptString n -> pr "  str *%s;\n" n
4511              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4512              | Bool n -> pr "  bool %s;\n" n
4513              | Int n -> pr "  int %s;\n" n
4514              | FileIn _ | FileOut _ -> ()
4515            ) args;
4516            pr "};\n\n"
4517       );
4518       (match fst style with
4519        | RErr -> ()
4520        | RInt n ->
4521            pr "struct %s_ret {\n" name;
4522            pr "  int %s;\n" n;
4523            pr "};\n\n"
4524        | RInt64 n ->
4525            pr "struct %s_ret {\n" name;
4526            pr "  hyper %s;\n" n;
4527            pr "};\n\n"
4528        | RBool n ->
4529            pr "struct %s_ret {\n" name;
4530            pr "  bool %s;\n" n;
4531            pr "};\n\n"
4532        | RConstString _ | RConstOptString _ ->
4533            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4534        | RString n ->
4535            pr "struct %s_ret {\n" name;
4536            pr "  string %s<>;\n" n;
4537            pr "};\n\n"
4538        | RStringList n ->
4539            pr "struct %s_ret {\n" name;
4540            pr "  str %s<>;\n" n;
4541            pr "};\n\n"
4542        | RStruct (n, typ) ->
4543            pr "struct %s_ret {\n" name;
4544            pr "  guestfs_int_%s %s;\n" typ n;
4545            pr "};\n\n"
4546        | RStructList (n, typ) ->
4547            pr "struct %s_ret {\n" name;
4548            pr "  guestfs_int_%s_list %s;\n" typ n;
4549            pr "};\n\n"
4550        | RHashtable n ->
4551            pr "struct %s_ret {\n" name;
4552            pr "  str %s<>;\n" n;
4553            pr "};\n\n"
4554        | RBufferOut n ->
4555            pr "struct %s_ret {\n" name;
4556            pr "  opaque %s<>;\n" n;
4557            pr "};\n\n"
4558       );
4559   ) daemon_functions;
4560
4561   (* Table of procedure numbers. *)
4562   pr "enum guestfs_procedure {\n";
4563   List.iter (
4564     fun (shortname, _, proc_nr, _, _, _, _) ->
4565       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4566   ) daemon_functions;
4567   pr "  GUESTFS_PROC_NR_PROCS\n";
4568   pr "};\n";
4569   pr "\n";
4570
4571   (* Having to choose a maximum message size is annoying for several
4572    * reasons (it limits what we can do in the API), but it (a) makes
4573    * the protocol a lot simpler, and (b) provides a bound on the size
4574    * of the daemon which operates in limited memory space.  For large
4575    * file transfers you should use FTP.
4576    *)
4577   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4578   pr "\n";
4579
4580   (* Message header, etc. *)
4581   pr "\
4582 /* The communication protocol is now documented in the guestfs(3)
4583  * manpage.
4584  */
4585
4586 const GUESTFS_PROGRAM = 0x2000F5F5;
4587 const GUESTFS_PROTOCOL_VERSION = 1;
4588
4589 /* These constants must be larger than any possible message length. */
4590 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4591 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4592
4593 enum guestfs_message_direction {
4594   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4595   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4596 };
4597
4598 enum guestfs_message_status {
4599   GUESTFS_STATUS_OK = 0,
4600   GUESTFS_STATUS_ERROR = 1
4601 };
4602
4603 const GUESTFS_ERROR_LEN = 256;
4604
4605 struct guestfs_message_error {
4606   string error_message<GUESTFS_ERROR_LEN>;
4607 };
4608
4609 struct guestfs_message_header {
4610   unsigned prog;                     /* GUESTFS_PROGRAM */
4611   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4612   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4613   guestfs_message_direction direction;
4614   unsigned serial;                   /* message serial number */
4615   guestfs_message_status status;
4616 };
4617
4618 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4619
4620 struct guestfs_chunk {
4621   int cancel;                        /* if non-zero, transfer is cancelled */
4622   /* data size is 0 bytes if the transfer has finished successfully */
4623   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4624 };
4625 "
4626
4627 (* Generate the guestfs-structs.h file. *)
4628 and generate_structs_h () =
4629   generate_header CStyle LGPLv2;
4630
4631   (* This is a public exported header file containing various
4632    * structures.  The structures are carefully written to have
4633    * exactly the same in-memory format as the XDR structures that
4634    * we use on the wire to the daemon.  The reason for creating
4635    * copies of these structures here is just so we don't have to
4636    * export the whole of guestfs_protocol.h (which includes much
4637    * unrelated and XDR-dependent stuff that we don't want to be
4638    * public, or required by clients).
4639    *
4640    * To reiterate, we will pass these structures to and from the
4641    * client with a simple assignment or memcpy, so the format
4642    * must be identical to what rpcgen / the RFC defines.
4643    *)
4644
4645   (* Public structures. *)
4646   List.iter (
4647     fun (typ, cols) ->
4648       pr "struct guestfs_%s {\n" typ;
4649       List.iter (
4650         function
4651         | name, FChar -> pr "  char %s;\n" name
4652         | name, FString -> pr "  char *%s;\n" name
4653         | name, FBuffer ->
4654             pr "  uint32_t %s_len;\n" name;
4655             pr "  char *%s;\n" name
4656         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4657         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4658         | name, FInt32 -> pr "  int32_t %s;\n" name
4659         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4660         | name, FInt64 -> pr "  int64_t %s;\n" name
4661         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4662       ) cols;
4663       pr "};\n";
4664       pr "\n";
4665       pr "struct guestfs_%s_list {\n" typ;
4666       pr "  uint32_t len;\n";
4667       pr "  struct guestfs_%s *val;\n" typ;
4668       pr "};\n";
4669       pr "\n";
4670       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4671       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4672       pr "\n"
4673   ) structs
4674
4675 (* Generate the guestfs-actions.h file. *)
4676 and generate_actions_h () =
4677   generate_header CStyle LGPLv2;
4678   List.iter (
4679     fun (shortname, style, _, _, _, _, _) ->
4680       let name = "guestfs_" ^ shortname in
4681       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4682         name style
4683   ) all_functions
4684
4685 (* Generate the guestfs-internal-actions.h file. *)
4686 and generate_internal_actions_h () =
4687   generate_header CStyle LGPLv2;
4688   List.iter (
4689     fun (shortname, style, _, _, _, _, _) ->
4690       let name = "guestfs__" ^ shortname in
4691       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4692         name style
4693   ) non_daemon_functions
4694
4695 (* Generate the client-side dispatch stubs. *)
4696 and generate_client_actions () =
4697   generate_header CStyle LGPLv2;
4698
4699   pr "\
4700 #include <stdio.h>
4701 #include <stdlib.h>
4702
4703 #include \"guestfs.h\"
4704 #include \"guestfs-internal-actions.h\"
4705 #include \"guestfs_protocol.h\"
4706
4707 #define error guestfs_error
4708 //#define perrorf guestfs_perrorf
4709 //#define safe_malloc guestfs_safe_malloc
4710 #define safe_realloc guestfs_safe_realloc
4711 //#define safe_strdup guestfs_safe_strdup
4712 #define safe_memdup guestfs_safe_memdup
4713
4714 /* Check the return message from a call for validity. */
4715 static int
4716 check_reply_header (guestfs_h *g,
4717                     const struct guestfs_message_header *hdr,
4718                     unsigned int proc_nr, unsigned int serial)
4719 {
4720   if (hdr->prog != GUESTFS_PROGRAM) {
4721     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4722     return -1;
4723   }
4724   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4725     error (g, \"wrong protocol version (%%d/%%d)\",
4726            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4727     return -1;
4728   }
4729   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4730     error (g, \"unexpected message direction (%%d/%%d)\",
4731            hdr->direction, GUESTFS_DIRECTION_REPLY);
4732     return -1;
4733   }
4734   if (hdr->proc != proc_nr) {
4735     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4736     return -1;
4737   }
4738   if (hdr->serial != serial) {
4739     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4740     return -1;
4741   }
4742
4743   return 0;
4744 }
4745
4746 /* Check we are in the right state to run a high-level action. */
4747 static int
4748 check_state (guestfs_h *g, const char *caller)
4749 {
4750   if (!guestfs__is_ready (g)) {
4751     if (guestfs__is_config (g) || guestfs__is_launching (g))
4752       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4753         caller);
4754     else
4755       error (g, \"%%s called from the wrong state, %%d != READY\",
4756         caller, guestfs__get_state (g));
4757     return -1;
4758   }
4759   return 0;
4760 }
4761
4762 ";
4763
4764   (* Generate code to generate guestfish call traces. *)
4765   let trace_call shortname style =
4766     pr "  if (guestfs__get_trace (g)) {\n";
4767
4768     let needs_i =
4769       List.exists (function
4770                    | StringList _ | DeviceList _ -> true
4771                    | _ -> false) (snd style) in
4772     if needs_i then (
4773       pr "    int i;\n";
4774       pr "\n"
4775     );
4776
4777     pr "    printf (\"%s\");\n" shortname;
4778     List.iter (
4779       function
4780       | String n                        (* strings *)
4781       | Device n
4782       | Pathname n
4783       | Dev_or_Path n
4784       | FileIn n
4785       | FileOut n ->
4786           (* guestfish doesn't support string escaping, so neither do we *)
4787           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4788       | OptString n ->                  (* string option *)
4789           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4790           pr "    else printf (\" null\");\n"
4791       | StringList n
4792       | DeviceList n ->                 (* string list *)
4793           pr "    putchar (' ');\n";
4794           pr "    putchar ('\"');\n";
4795           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4796           pr "      if (i > 0) putchar (' ');\n";
4797           pr "      fputs (%s[i], stdout);\n" n;
4798           pr "    }\n";
4799           pr "    putchar ('\"');\n";
4800       | Bool n ->                       (* boolean *)
4801           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4802       | Int n ->                        (* int *)
4803           pr "    printf (\" %%d\", %s);\n" n
4804     ) (snd style);
4805     pr "    putchar ('\\n');\n";
4806     pr "  }\n";
4807     pr "\n";
4808   in
4809
4810   (* For non-daemon functions, generate a wrapper around each function. *)
4811   List.iter (
4812     fun (shortname, style, _, _, _, _, _) ->
4813       let name = "guestfs_" ^ shortname in
4814
4815       generate_prototype ~extern:false ~semicolon:false ~newline:true
4816         ~handle:"g" name style;
4817       pr "{\n";
4818       trace_call shortname style;
4819       pr "  return guestfs__%s " shortname;
4820       generate_c_call_args ~handle:"g" style;
4821       pr ";\n";
4822       pr "}\n";
4823       pr "\n"
4824   ) non_daemon_functions;
4825
4826   (* Client-side stubs for each function. *)
4827   List.iter (
4828     fun (shortname, style, _, _, _, _, _) ->
4829       let name = "guestfs_" ^ shortname in
4830
4831       (* Generate the action stub. *)
4832       generate_prototype ~extern:false ~semicolon:false ~newline:true
4833         ~handle:"g" name style;
4834
4835       let error_code =
4836         match fst style with
4837         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4838         | RConstString _ | RConstOptString _ ->
4839             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4840         | RString _ | RStringList _
4841         | RStruct _ | RStructList _
4842         | RHashtable _ | RBufferOut _ ->
4843             "NULL" in
4844
4845       pr "{\n";
4846
4847       (match snd style with
4848        | [] -> ()
4849        | _ -> pr "  struct %s_args args;\n" name
4850       );
4851
4852       pr "  guestfs_message_header hdr;\n";
4853       pr "  guestfs_message_error err;\n";
4854       let has_ret =
4855         match fst style with
4856         | RErr -> false
4857         | RConstString _ | RConstOptString _ ->
4858             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4859         | RInt _ | RInt64 _
4860         | RBool _ | RString _ | RStringList _
4861         | RStruct _ | RStructList _
4862         | RHashtable _ | RBufferOut _ ->
4863             pr "  struct %s_ret ret;\n" name;
4864             true in
4865
4866       pr "  int serial;\n";
4867       pr "  int r;\n";
4868       pr "\n";
4869       trace_call shortname style;
4870       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4871       pr "  guestfs___set_busy (g);\n";
4872       pr "\n";
4873
4874       (* Send the main header and arguments. *)
4875       (match snd style with
4876        | [] ->
4877            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4878              (String.uppercase shortname)
4879        | args ->
4880            List.iter (
4881              function
4882              | Pathname n | Device n | Dev_or_Path n | String n ->
4883                  pr "  args.%s = (char *) %s;\n" n n
4884              | OptString n ->
4885                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4886              | StringList n | DeviceList n ->
4887                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4888                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4889              | Bool n ->
4890                  pr "  args.%s = %s;\n" n n
4891              | Int n ->
4892                  pr "  args.%s = %s;\n" n n
4893              | FileIn _ | FileOut _ -> ()
4894            ) args;
4895            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4896              (String.uppercase shortname);
4897            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4898              name;
4899       );
4900       pr "  if (serial == -1) {\n";
4901       pr "    guestfs___end_busy (g);\n";
4902       pr "    return %s;\n" error_code;
4903       pr "  }\n";
4904       pr "\n";
4905
4906       (* Send any additional files (FileIn) requested. *)
4907       let need_read_reply_label = ref false in
4908       List.iter (
4909         function
4910         | FileIn n ->
4911             pr "  r = guestfs___send_file (g, %s);\n" n;
4912             pr "  if (r == -1) {\n";
4913             pr "    guestfs___end_busy (g);\n";
4914             pr "    return %s;\n" error_code;
4915             pr "  }\n";
4916             pr "  if (r == -2) /* daemon cancelled */\n";
4917             pr "    goto read_reply;\n";
4918             need_read_reply_label := true;
4919             pr "\n";
4920         | _ -> ()
4921       ) (snd style);
4922
4923       (* Wait for the reply from the remote end. *)
4924       if !need_read_reply_label then pr " read_reply:\n";
4925       pr "  memset (&hdr, 0, sizeof hdr);\n";
4926       pr "  memset (&err, 0, sizeof err);\n";
4927       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
4928       pr "\n";
4929       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
4930       if not has_ret then
4931         pr "NULL, NULL"
4932       else
4933         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
4934       pr ");\n";
4935
4936       pr "  if (r == -1) {\n";
4937       pr "    guestfs___end_busy (g);\n";
4938       pr "    return %s;\n" error_code;
4939       pr "  }\n";
4940       pr "\n";
4941
4942       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4943         (String.uppercase shortname);
4944       pr "    guestfs___end_busy (g);\n";
4945       pr "    return %s;\n" error_code;
4946       pr "  }\n";
4947       pr "\n";
4948
4949       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
4950       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
4951       pr "    free (err.error_message);\n";
4952       pr "    guestfs___end_busy (g);\n";
4953       pr "    return %s;\n" error_code;
4954       pr "  }\n";
4955       pr "\n";
4956
4957       (* Expecting to receive further files (FileOut)? *)
4958       List.iter (
4959         function
4960         | FileOut n ->
4961             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
4962             pr "    guestfs___end_busy (g);\n";
4963             pr "    return %s;\n" error_code;
4964             pr "  }\n";
4965             pr "\n";
4966         | _ -> ()
4967       ) (snd style);
4968
4969       pr "  guestfs___end_busy (g);\n";
4970
4971       (match fst style with
4972        | RErr -> pr "  return 0;\n"
4973        | RInt n | RInt64 n | RBool n ->
4974            pr "  return ret.%s;\n" n
4975        | RConstString _ | RConstOptString _ ->
4976            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4977        | RString n ->
4978            pr "  return ret.%s; /* caller will free */\n" n
4979        | RStringList n | RHashtable n ->
4980            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4981            pr "  ret.%s.%s_val =\n" n n;
4982            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
4983            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
4984              n n;
4985            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
4986            pr "  return ret.%s.%s_val;\n" n n
4987        | RStruct (n, _) ->
4988            pr "  /* caller will free this */\n";
4989            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4990        | RStructList (n, _) ->
4991            pr "  /* caller will free this */\n";
4992            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4993        | RBufferOut n ->
4994            pr "  *size_r = ret.%s.%s_len;\n" n n;
4995            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
4996       );
4997
4998       pr "}\n\n"
4999   ) daemon_functions;
5000
5001   (* Functions to free structures. *)
5002   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5003   pr " * structure format is identical to the XDR format.  See note in\n";
5004   pr " * generator.ml.\n";
5005   pr " */\n";
5006   pr "\n";
5007
5008   List.iter (
5009     fun (typ, _) ->
5010       pr "void\n";
5011       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5012       pr "{\n";
5013       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5014       pr "  free (x);\n";
5015       pr "}\n";
5016       pr "\n";
5017
5018       pr "void\n";
5019       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5020       pr "{\n";
5021       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5022       pr "  free (x);\n";
5023       pr "}\n";
5024       pr "\n";
5025
5026   ) structs;
5027
5028 (* Generate daemon/actions.h. *)
5029 and generate_daemon_actions_h () =
5030   generate_header CStyle GPLv2;
5031
5032   pr "#include \"../src/guestfs_protocol.h\"\n";
5033   pr "\n";
5034
5035   List.iter (
5036     fun (name, style, _, _, _, _, _) ->
5037       generate_prototype
5038         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5039         name style;
5040   ) daemon_functions
5041
5042 (* Generate the server-side stubs. *)
5043 and generate_daemon_actions () =
5044   generate_header CStyle GPLv2;
5045
5046   pr "#include <config.h>\n";
5047   pr "\n";
5048   pr "#include <stdio.h>\n";
5049   pr "#include <stdlib.h>\n";
5050   pr "#include <string.h>\n";
5051   pr "#include <inttypes.h>\n";
5052   pr "#include <rpc/types.h>\n";
5053   pr "#include <rpc/xdr.h>\n";
5054   pr "\n";
5055   pr "#include \"daemon.h\"\n";
5056   pr "#include \"c-ctype.h\"\n";
5057   pr "#include \"../src/guestfs_protocol.h\"\n";
5058   pr "#include \"actions.h\"\n";
5059   pr "\n";
5060
5061   List.iter (
5062     fun (name, style, _, _, _, _, _) ->
5063       (* Generate server-side stubs. *)
5064       pr "static void %s_stub (XDR *xdr_in)\n" name;
5065       pr "{\n";
5066       let error_code =
5067         match fst style with
5068         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5069         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5070         | RBool _ -> pr "  int r;\n"; "-1"
5071         | RConstString _ | RConstOptString _ ->
5072             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5073         | RString _ -> pr "  char *r;\n"; "NULL"
5074         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5075         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5076         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5077         | RBufferOut _ ->
5078             pr "  size_t size;\n";
5079             pr "  char *r;\n";
5080             "NULL" in
5081
5082       (match snd style with
5083        | [] -> ()
5084        | args ->
5085            pr "  struct guestfs_%s_args args;\n" name;
5086            List.iter (
5087              function
5088              | Device n | Dev_or_Path n
5089              | Pathname n
5090              | String n -> ()
5091              | OptString n -> pr "  char *%s;\n" n
5092              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5093              | Bool n -> pr "  int %s;\n" n
5094              | Int n -> pr "  int %s;\n" n
5095              | FileIn _ | FileOut _ -> ()
5096            ) args
5097       );
5098       pr "\n";
5099
5100       (match snd style with
5101        | [] -> ()
5102        | args ->
5103            pr "  memset (&args, 0, sizeof args);\n";
5104            pr "\n";
5105            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5106            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5107            pr "    return;\n";
5108            pr "  }\n";
5109            let pr_args n =
5110              pr "  char *%s = args.%s;\n" n n
5111            in
5112            let pr_list_handling_code n =
5113              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5114              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5115              pr "  if (%s == NULL) {\n" n;
5116              pr "    reply_with_perror (\"realloc\");\n";
5117              pr "    goto done;\n";
5118              pr "  }\n";
5119              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5120              pr "  args.%s.%s_val = %s;\n" n n n;
5121            in
5122            List.iter (
5123              function
5124              | Pathname n ->
5125                  pr_args n;
5126                  pr "  ABS_PATH (%s, goto done);\n" n;
5127              | Device n ->
5128                  pr_args n;
5129                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5130              | Dev_or_Path n ->
5131                  pr_args n;
5132                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5133              | String n -> pr_args n
5134              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5135              | StringList n ->
5136                  pr_list_handling_code n;
5137              | DeviceList n ->
5138                  pr_list_handling_code n;
5139                  pr "  /* Ensure that each is a device,\n";
5140                  pr "   * and perform device name translation. */\n";
5141                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5142                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5143                  pr "  }\n";
5144              | Bool n -> pr "  %s = args.%s;\n" n n
5145              | Int n -> pr "  %s = args.%s;\n" n n
5146              | FileIn _ | FileOut _ -> ()
5147            ) args;
5148            pr "\n"
5149       );
5150
5151
5152       (* this is used at least for do_equal *)
5153       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5154         (* Emit NEED_ROOT just once, even when there are two or
5155            more Pathname args *)
5156         pr "  NEED_ROOT (goto done);\n";
5157       );
5158
5159       (* Don't want to call the impl with any FileIn or FileOut
5160        * parameters, since these go "outside" the RPC protocol.
5161        *)
5162       let args' =
5163         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5164           (snd style) in
5165       pr "  r = do_%s " name;
5166       generate_c_call_args (fst style, args');
5167       pr ";\n";
5168
5169       pr "  if (r == %s)\n" error_code;
5170       pr "    /* do_%s has already called reply_with_error */\n" name;
5171       pr "    goto done;\n";
5172       pr "\n";
5173
5174       (* If there are any FileOut parameters, then the impl must
5175        * send its own reply.
5176        *)
5177       let no_reply =
5178         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5179       if no_reply then
5180         pr "  /* do_%s has already sent a reply */\n" name
5181       else (
5182         match fst style with
5183         | RErr -> pr "  reply (NULL, NULL);\n"
5184         | RInt n | RInt64 n | RBool n ->
5185             pr "  struct guestfs_%s_ret ret;\n" name;
5186             pr "  ret.%s = r;\n" n;
5187             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5188               name
5189         | RConstString _ | RConstOptString _ ->
5190             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5191         | RString n ->
5192             pr "  struct guestfs_%s_ret ret;\n" name;
5193             pr "  ret.%s = r;\n" n;
5194             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5195               name;
5196             pr "  free (r);\n"
5197         | RStringList n | RHashtable n ->
5198             pr "  struct guestfs_%s_ret ret;\n" name;
5199             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5200             pr "  ret.%s.%s_val = r;\n" n n;
5201             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5202               name;
5203             pr "  free_strings (r);\n"
5204         | RStruct (n, _) ->
5205             pr "  struct guestfs_%s_ret ret;\n" name;
5206             pr "  ret.%s = *r;\n" n;
5207             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5208               name;
5209             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5210               name
5211         | RStructList (n, _) ->
5212             pr "  struct guestfs_%s_ret ret;\n" name;
5213             pr "  ret.%s = *r;\n" n;
5214             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5215               name;
5216             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5217               name
5218         | RBufferOut n ->
5219             pr "  struct guestfs_%s_ret ret;\n" name;
5220             pr "  ret.%s.%s_val = r;\n" n n;
5221             pr "  ret.%s.%s_len = size;\n" n n;
5222             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5223               name;
5224             pr "  free (r);\n"
5225       );
5226
5227       (* Free the args. *)
5228       (match snd style with
5229        | [] ->
5230            pr "done: ;\n";
5231        | _ ->
5232            pr "done:\n";
5233            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5234              name
5235       );
5236
5237       pr "}\n\n";
5238   ) daemon_functions;
5239
5240   (* Dispatch function. *)
5241   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5242   pr "{\n";
5243   pr "  switch (proc_nr) {\n";
5244
5245   List.iter (
5246     fun (name, style, _, _, _, _, _) ->
5247       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5248       pr "      %s_stub (xdr_in);\n" name;
5249       pr "      break;\n"
5250   ) daemon_functions;
5251
5252   pr "    default:\n";
5253   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";
5254   pr "  }\n";
5255   pr "}\n";
5256   pr "\n";
5257
5258   (* LVM columns and tokenization functions. *)
5259   (* XXX This generates crap code.  We should rethink how we
5260    * do this parsing.
5261    *)
5262   List.iter (
5263     function
5264     | typ, cols ->
5265         pr "static const char *lvm_%s_cols = \"%s\";\n"
5266           typ (String.concat "," (List.map fst cols));
5267         pr "\n";
5268
5269         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5270         pr "{\n";
5271         pr "  char *tok, *p, *next;\n";
5272         pr "  int i, j;\n";
5273         pr "\n";
5274         (*
5275           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5276           pr "\n";
5277         *)
5278         pr "  if (!str) {\n";
5279         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5280         pr "    return -1;\n";
5281         pr "  }\n";
5282         pr "  if (!*str || c_isspace (*str)) {\n";
5283         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5284         pr "    return -1;\n";
5285         pr "  }\n";
5286         pr "  tok = str;\n";
5287         List.iter (
5288           fun (name, coltype) ->
5289             pr "  if (!tok) {\n";
5290             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5291             pr "    return -1;\n";
5292             pr "  }\n";
5293             pr "  p = strchrnul (tok, ',');\n";
5294             pr "  if (*p) next = p+1; else next = NULL;\n";
5295             pr "  *p = '\\0';\n";
5296             (match coltype with
5297              | FString ->
5298                  pr "  r->%s = strdup (tok);\n" name;
5299                  pr "  if (r->%s == NULL) {\n" name;
5300                  pr "    perror (\"strdup\");\n";
5301                  pr "    return -1;\n";
5302                  pr "  }\n"
5303              | FUUID ->
5304                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5305                  pr "    if (tok[j] == '\\0') {\n";
5306                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5307                  pr "      return -1;\n";
5308                  pr "    } else if (tok[j] != '-')\n";
5309                  pr "      r->%s[i++] = tok[j];\n" name;
5310                  pr "  }\n";
5311              | FBytes ->
5312                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5313                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5314                  pr "    return -1;\n";
5315                  pr "  }\n";
5316              | FInt64 ->
5317                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5318                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5319                  pr "    return -1;\n";
5320                  pr "  }\n";
5321              | FOptPercent ->
5322                  pr "  if (tok[0] == '\\0')\n";
5323                  pr "    r->%s = -1;\n" name;
5324                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5325                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5326                  pr "    return -1;\n";
5327                  pr "  }\n";
5328              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5329                  assert false (* can never be an LVM column *)
5330             );
5331             pr "  tok = next;\n";
5332         ) cols;
5333
5334         pr "  if (tok != NULL) {\n";
5335         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5336         pr "    return -1;\n";
5337         pr "  }\n";
5338         pr "  return 0;\n";
5339         pr "}\n";
5340         pr "\n";
5341
5342         pr "guestfs_int_lvm_%s_list *\n" typ;
5343         pr "parse_command_line_%ss (void)\n" typ;
5344         pr "{\n";
5345         pr "  char *out, *err;\n";
5346         pr "  char *p, *pend;\n";
5347         pr "  int r, i;\n";
5348         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5349         pr "  void *newp;\n";
5350         pr "\n";
5351         pr "  ret = malloc (sizeof *ret);\n";
5352         pr "  if (!ret) {\n";
5353         pr "    reply_with_perror (\"malloc\");\n";
5354         pr "    return NULL;\n";
5355         pr "  }\n";
5356         pr "\n";
5357         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5358         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5359         pr "\n";
5360         pr "  r = command (&out, &err,\n";
5361         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5362         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5363         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5364         pr "  if (r == -1) {\n";
5365         pr "    reply_with_error (\"%%s\", err);\n";
5366         pr "    free (out);\n";
5367         pr "    free (err);\n";
5368         pr "    free (ret);\n";
5369         pr "    return NULL;\n";
5370         pr "  }\n";
5371         pr "\n";
5372         pr "  free (err);\n";
5373         pr "\n";
5374         pr "  /* Tokenize each line of the output. */\n";
5375         pr "  p = out;\n";
5376         pr "  i = 0;\n";
5377         pr "  while (p) {\n";
5378         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5379         pr "    if (pend) {\n";
5380         pr "      *pend = '\\0';\n";
5381         pr "      pend++;\n";
5382         pr "    }\n";
5383         pr "\n";
5384         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5385         pr "      p++;\n";
5386         pr "\n";
5387         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5388         pr "      p = pend;\n";
5389         pr "      continue;\n";
5390         pr "    }\n";
5391         pr "\n";
5392         pr "    /* Allocate some space to store this next entry. */\n";
5393         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5394         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5395         pr "    if (newp == NULL) {\n";
5396         pr "      reply_with_perror (\"realloc\");\n";
5397         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5398         pr "      free (ret);\n";
5399         pr "      free (out);\n";
5400         pr "      return NULL;\n";
5401         pr "    }\n";
5402         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5403         pr "\n";
5404         pr "    /* Tokenize the next entry. */\n";
5405         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5406         pr "    if (r == -1) {\n";
5407         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5408         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5409         pr "      free (ret);\n";
5410         pr "      free (out);\n";
5411         pr "      return NULL;\n";
5412         pr "    }\n";
5413         pr "\n";
5414         pr "    ++i;\n";
5415         pr "    p = pend;\n";
5416         pr "  }\n";
5417         pr "\n";
5418         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5419         pr "\n";
5420         pr "  free (out);\n";
5421         pr "  return ret;\n";
5422         pr "}\n"
5423
5424   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5425
5426 (* Generate a list of function names, for debugging in the daemon.. *)
5427 and generate_daemon_names () =
5428   generate_header CStyle GPLv2;
5429
5430   pr "#include <config.h>\n";
5431   pr "\n";
5432   pr "#include \"daemon.h\"\n";
5433   pr "\n";
5434
5435   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5436   pr "const char *function_names[] = {\n";
5437   List.iter (
5438     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5439   ) daemon_functions;
5440   pr "};\n";
5441
5442 (* Generate the tests. *)
5443 and generate_tests () =
5444   generate_header CStyle GPLv2;
5445
5446   pr "\
5447 #include <stdio.h>
5448 #include <stdlib.h>
5449 #include <string.h>
5450 #include <unistd.h>
5451 #include <sys/types.h>
5452 #include <fcntl.h>
5453
5454 #include \"guestfs.h\"
5455
5456 static guestfs_h *g;
5457 static int suppress_error = 0;
5458
5459 static void print_error (guestfs_h *g, void *data, const char *msg)
5460 {
5461   if (!suppress_error)
5462     fprintf (stderr, \"%%s\\n\", msg);
5463 }
5464
5465 /* FIXME: nearly identical code appears in fish.c */
5466 static void print_strings (char *const *argv)
5467 {
5468   int argc;
5469
5470   for (argc = 0; argv[argc] != NULL; ++argc)
5471     printf (\"\\t%%s\\n\", argv[argc]);
5472 }
5473
5474 /*
5475 static void print_table (char const *const *argv)
5476 {
5477   int i;
5478
5479   for (i = 0; argv[i] != NULL; i += 2)
5480     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5481 }
5482 */
5483
5484 ";
5485
5486   (* Generate a list of commands which are not tested anywhere. *)
5487   pr "static void no_test_warnings (void)\n";
5488   pr "{\n";
5489
5490   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5491   List.iter (
5492     fun (_, _, _, _, tests, _, _) ->
5493       let tests = filter_map (
5494         function
5495         | (_, (Always|If _|Unless _), test) -> Some test
5496         | (_, Disabled, _) -> None
5497       ) tests in
5498       let seq = List.concat (List.map seq_of_test tests) in
5499       let cmds_tested = List.map List.hd seq in
5500       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5501   ) all_functions;
5502
5503   List.iter (
5504     fun (name, _, _, _, _, _, _) ->
5505       if not (Hashtbl.mem hash name) then
5506         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5507   ) all_functions;
5508
5509   pr "}\n";
5510   pr "\n";
5511
5512   (* Generate the actual tests.  Note that we generate the tests
5513    * in reverse order, deliberately, so that (in general) the
5514    * newest tests run first.  This makes it quicker and easier to
5515    * debug them.
5516    *)
5517   let test_names =
5518     List.map (
5519       fun (name, _, _, _, tests, _, _) ->
5520         mapi (generate_one_test name) tests
5521     ) (List.rev all_functions) in
5522   let test_names = List.concat test_names in
5523   let nr_tests = List.length test_names in
5524
5525   pr "\
5526 int main (int argc, char *argv[])
5527 {
5528   char c = 0;
5529   unsigned long int n_failed = 0;
5530   const char *filename;
5531   int fd;
5532   int nr_tests, test_num = 0;
5533
5534   setbuf (stdout, NULL);
5535
5536   no_test_warnings ();
5537
5538   g = guestfs_create ();
5539   if (g == NULL) {
5540     printf (\"guestfs_create FAILED\\n\");
5541     exit (1);
5542   }
5543
5544   guestfs_set_error_handler (g, print_error, NULL);
5545
5546   guestfs_set_path (g, \"../appliance\");
5547
5548   filename = \"test1.img\";
5549   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5550   if (fd == -1) {
5551     perror (filename);
5552     exit (1);
5553   }
5554   if (lseek (fd, %d, SEEK_SET) == -1) {
5555     perror (\"lseek\");
5556     close (fd);
5557     unlink (filename);
5558     exit (1);
5559   }
5560   if (write (fd, &c, 1) == -1) {
5561     perror (\"write\");
5562     close (fd);
5563     unlink (filename);
5564     exit (1);
5565   }
5566   if (close (fd) == -1) {
5567     perror (filename);
5568     unlink (filename);
5569     exit (1);
5570   }
5571   if (guestfs_add_drive (g, filename) == -1) {
5572     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5573     exit (1);
5574   }
5575
5576   filename = \"test2.img\";
5577   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5578   if (fd == -1) {
5579     perror (filename);
5580     exit (1);
5581   }
5582   if (lseek (fd, %d, SEEK_SET) == -1) {
5583     perror (\"lseek\");
5584     close (fd);
5585     unlink (filename);
5586     exit (1);
5587   }
5588   if (write (fd, &c, 1) == -1) {
5589     perror (\"write\");
5590     close (fd);
5591     unlink (filename);
5592     exit (1);
5593   }
5594   if (close (fd) == -1) {
5595     perror (filename);
5596     unlink (filename);
5597     exit (1);
5598   }
5599   if (guestfs_add_drive (g, filename) == -1) {
5600     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5601     exit (1);
5602   }
5603
5604   filename = \"test3.img\";
5605   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5606   if (fd == -1) {
5607     perror (filename);
5608     exit (1);
5609   }
5610   if (lseek (fd, %d, SEEK_SET) == -1) {
5611     perror (\"lseek\");
5612     close (fd);
5613     unlink (filename);
5614     exit (1);
5615   }
5616   if (write (fd, &c, 1) == -1) {
5617     perror (\"write\");
5618     close (fd);
5619     unlink (filename);
5620     exit (1);
5621   }
5622   if (close (fd) == -1) {
5623     perror (filename);
5624     unlink (filename);
5625     exit (1);
5626   }
5627   if (guestfs_add_drive (g, filename) == -1) {
5628     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5629     exit (1);
5630   }
5631
5632   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5633     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5634     exit (1);
5635   }
5636
5637   if (guestfs_launch (g) == -1) {
5638     printf (\"guestfs_launch FAILED\\n\");
5639     exit (1);
5640   }
5641
5642   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5643   alarm (600);
5644
5645   /* Cancel previous alarm. */
5646   alarm (0);
5647
5648   nr_tests = %d;
5649
5650 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5651
5652   iteri (
5653     fun i test_name ->
5654       pr "  test_num++;\n";
5655       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5656       pr "  if (%s () == -1) {\n" test_name;
5657       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5658       pr "    n_failed++;\n";
5659       pr "  }\n";
5660   ) test_names;
5661   pr "\n";
5662
5663   pr "  guestfs_close (g);\n";
5664   pr "  unlink (\"test1.img\");\n";
5665   pr "  unlink (\"test2.img\");\n";
5666   pr "  unlink (\"test3.img\");\n";
5667   pr "\n";
5668
5669   pr "  if (n_failed > 0) {\n";
5670   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5671   pr "    exit (1);\n";
5672   pr "  }\n";
5673   pr "\n";
5674
5675   pr "  exit (0);\n";
5676   pr "}\n"
5677
5678 and generate_one_test name i (init, prereq, test) =
5679   let test_name = sprintf "test_%s_%d" name i in
5680
5681   pr "\
5682 static int %s_skip (void)
5683 {
5684   const char *str;
5685
5686   str = getenv (\"TEST_ONLY\");
5687   if (str)
5688     return strstr (str, \"%s\") == NULL;
5689   str = getenv (\"SKIP_%s\");
5690   if (str && strcmp (str, \"1\") == 0) return 1;
5691   str = getenv (\"SKIP_TEST_%s\");
5692   if (str && strcmp (str, \"1\") == 0) return 1;
5693   return 0;
5694 }
5695
5696 " test_name name (String.uppercase test_name) (String.uppercase name);
5697
5698   (match prereq with
5699    | Disabled | Always -> ()
5700    | If code | Unless code ->
5701        pr "static int %s_prereq (void)\n" test_name;
5702        pr "{\n";
5703        pr "  %s\n" code;
5704        pr "}\n";
5705        pr "\n";
5706   );
5707
5708   pr "\
5709 static int %s (void)
5710 {
5711   if (%s_skip ()) {
5712     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5713     return 0;
5714   }
5715
5716 " test_name test_name test_name;
5717
5718   (match prereq with
5719    | Disabled ->
5720        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5721    | If _ ->
5722        pr "  if (! %s_prereq ()) {\n" test_name;
5723        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5724        pr "    return 0;\n";
5725        pr "  }\n";
5726        pr "\n";
5727        generate_one_test_body name i test_name init test;
5728    | Unless _ ->
5729        pr "  if (%s_prereq ()) {\n" test_name;
5730        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5731        pr "    return 0;\n";
5732        pr "  }\n";
5733        pr "\n";
5734        generate_one_test_body name i test_name init test;
5735    | Always ->
5736        generate_one_test_body name i test_name init test
5737   );
5738
5739   pr "  return 0;\n";
5740   pr "}\n";
5741   pr "\n";
5742   test_name
5743
5744 and generate_one_test_body name i test_name init test =
5745   (match init with
5746    | InitNone (* XXX at some point, InitNone and InitEmpty became
5747                * folded together as the same thing.  Really we should
5748                * make InitNone do nothing at all, but the tests may
5749                * need to be checked to make sure this is OK.
5750                *)
5751    | InitEmpty ->
5752        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
5753        List.iter (generate_test_command_call test_name)
5754          [["blockdev_setrw"; "/dev/sda"];
5755           ["umount_all"];
5756           ["lvm_remove_all"]]
5757    | InitPartition ->
5758        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5759        List.iter (generate_test_command_call test_name)
5760          [["blockdev_setrw"; "/dev/sda"];
5761           ["umount_all"];
5762           ["lvm_remove_all"];
5763           ["sfdiskM"; "/dev/sda"; ","]]
5764    | InitBasicFS ->
5765        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5766        List.iter (generate_test_command_call test_name)
5767          [["blockdev_setrw"; "/dev/sda"];
5768           ["umount_all"];
5769           ["lvm_remove_all"];
5770           ["sfdiskM"; "/dev/sda"; ","];
5771           ["mkfs"; "ext2"; "/dev/sda1"];
5772           ["mount"; "/dev/sda1"; "/"]]
5773    | InitBasicFSonLVM ->
5774        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5775          test_name;
5776        List.iter (generate_test_command_call test_name)
5777          [["blockdev_setrw"; "/dev/sda"];
5778           ["umount_all"];
5779           ["lvm_remove_all"];
5780           ["sfdiskM"; "/dev/sda"; ","];
5781           ["pvcreate"; "/dev/sda1"];
5782           ["vgcreate"; "VG"; "/dev/sda1"];
5783           ["lvcreate"; "LV"; "VG"; "8"];
5784           ["mkfs"; "ext2"; "/dev/VG/LV"];
5785           ["mount"; "/dev/VG/LV"; "/"]]
5786    | InitISOFS ->
5787        pr "  /* InitISOFS for %s */\n" test_name;
5788        List.iter (generate_test_command_call test_name)
5789          [["blockdev_setrw"; "/dev/sda"];
5790           ["umount_all"];
5791           ["lvm_remove_all"];
5792           ["mount_ro"; "/dev/sdd"; "/"]]
5793   );
5794
5795   let get_seq_last = function
5796     | [] ->
5797         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5798           test_name
5799     | seq ->
5800         let seq = List.rev seq in
5801         List.rev (List.tl seq), List.hd seq
5802   in
5803
5804   match test with
5805   | TestRun seq ->
5806       pr "  /* TestRun for %s (%d) */\n" name i;
5807       List.iter (generate_test_command_call test_name) seq
5808   | TestOutput (seq, expected) ->
5809       pr "  /* TestOutput for %s (%d) */\n" name i;
5810       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5811       let seq, last = get_seq_last seq in
5812       let test () =
5813         pr "    if (strcmp (r, expected) != 0) {\n";
5814         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5815         pr "      return -1;\n";
5816         pr "    }\n"
5817       in
5818       List.iter (generate_test_command_call test_name) seq;
5819       generate_test_command_call ~test test_name last
5820   | TestOutputList (seq, expected) ->
5821       pr "  /* TestOutputList for %s (%d) */\n" name i;
5822       let seq, last = get_seq_last seq in
5823       let test () =
5824         iteri (
5825           fun i str ->
5826             pr "    if (!r[%d]) {\n" i;
5827             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5828             pr "      print_strings (r);\n";
5829             pr "      return -1;\n";
5830             pr "    }\n";
5831             pr "    {\n";
5832             pr "      const char *expected = \"%s\";\n" (c_quote str);
5833             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5834             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5835             pr "        return -1;\n";
5836             pr "      }\n";
5837             pr "    }\n"
5838         ) expected;
5839         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5840         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5841           test_name;
5842         pr "      print_strings (r);\n";
5843         pr "      return -1;\n";
5844         pr "    }\n"
5845       in
5846       List.iter (generate_test_command_call test_name) seq;
5847       generate_test_command_call ~test test_name last
5848   | TestOutputListOfDevices (seq, expected) ->
5849       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5850       let seq, last = get_seq_last seq in
5851       let test () =
5852         iteri (
5853           fun i str ->
5854             pr "    if (!r[%d]) {\n" i;
5855             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5856             pr "      print_strings (r);\n";
5857             pr "      return -1;\n";
5858             pr "    }\n";
5859             pr "    {\n";
5860             pr "      const char *expected = \"%s\";\n" (c_quote str);
5861             pr "      r[%d][5] = 's';\n" i;
5862             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5863             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5864             pr "        return -1;\n";
5865             pr "      }\n";
5866             pr "    }\n"
5867         ) expected;
5868         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5869         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5870           test_name;
5871         pr "      print_strings (r);\n";
5872         pr "      return -1;\n";
5873         pr "    }\n"
5874       in
5875       List.iter (generate_test_command_call test_name) seq;
5876       generate_test_command_call ~test test_name last
5877   | TestOutputInt (seq, expected) ->
5878       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5879       let seq, last = get_seq_last seq in
5880       let test () =
5881         pr "    if (r != %d) {\n" expected;
5882         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5883           test_name expected;
5884         pr "               (int) r);\n";
5885         pr "      return -1;\n";
5886         pr "    }\n"
5887       in
5888       List.iter (generate_test_command_call test_name) seq;
5889       generate_test_command_call ~test test_name last
5890   | TestOutputIntOp (seq, op, expected) ->
5891       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5892       let seq, last = get_seq_last seq in
5893       let test () =
5894         pr "    if (! (r %s %d)) {\n" op expected;
5895         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5896           test_name op expected;
5897         pr "               (int) r);\n";
5898         pr "      return -1;\n";
5899         pr "    }\n"
5900       in
5901       List.iter (generate_test_command_call test_name) seq;
5902       generate_test_command_call ~test test_name last
5903   | TestOutputTrue seq ->
5904       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5905       let seq, last = get_seq_last seq in
5906       let test () =
5907         pr "    if (!r) {\n";
5908         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5909           test_name;
5910         pr "      return -1;\n";
5911         pr "    }\n"
5912       in
5913       List.iter (generate_test_command_call test_name) seq;
5914       generate_test_command_call ~test test_name last
5915   | TestOutputFalse seq ->
5916       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5917       let seq, last = get_seq_last seq in
5918       let test () =
5919         pr "    if (r) {\n";
5920         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5921           test_name;
5922         pr "      return -1;\n";
5923         pr "    }\n"
5924       in
5925       List.iter (generate_test_command_call test_name) seq;
5926       generate_test_command_call ~test test_name last
5927   | TestOutputLength (seq, expected) ->
5928       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5929       let seq, last = get_seq_last seq in
5930       let test () =
5931         pr "    int j;\n";
5932         pr "    for (j = 0; j < %d; ++j)\n" expected;
5933         pr "      if (r[j] == NULL) {\n";
5934         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5935           test_name;
5936         pr "        print_strings (r);\n";
5937         pr "        return -1;\n";
5938         pr "      }\n";
5939         pr "    if (r[j] != NULL) {\n";
5940         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5941           test_name;
5942         pr "      print_strings (r);\n";
5943         pr "      return -1;\n";
5944         pr "    }\n"
5945       in
5946       List.iter (generate_test_command_call test_name) seq;
5947       generate_test_command_call ~test test_name last
5948   | TestOutputBuffer (seq, expected) ->
5949       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5950       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5951       let seq, last = get_seq_last seq in
5952       let len = String.length expected in
5953       let test () =
5954         pr "    if (size != %d) {\n" len;
5955         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5956         pr "      return -1;\n";
5957         pr "    }\n";
5958         pr "    if (strncmp (r, expected, size) != 0) {\n";
5959         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5960         pr "      return -1;\n";
5961         pr "    }\n"
5962       in
5963       List.iter (generate_test_command_call test_name) seq;
5964       generate_test_command_call ~test test_name last
5965   | TestOutputStruct (seq, checks) ->
5966       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5967       let seq, last = get_seq_last seq in
5968       let test () =
5969         List.iter (
5970           function
5971           | CompareWithInt (field, expected) ->
5972               pr "    if (r->%s != %d) {\n" field expected;
5973               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5974                 test_name field expected;
5975               pr "               (int) r->%s);\n" field;
5976               pr "      return -1;\n";
5977               pr "    }\n"
5978           | CompareWithIntOp (field, op, expected) ->
5979               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5980               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5981                 test_name field op expected;
5982               pr "               (int) r->%s);\n" field;
5983               pr "      return -1;\n";
5984               pr "    }\n"
5985           | CompareWithString (field, expected) ->
5986               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5987               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5988                 test_name field expected;
5989               pr "               r->%s);\n" field;
5990               pr "      return -1;\n";
5991               pr "    }\n"
5992           | CompareFieldsIntEq (field1, field2) ->
5993               pr "    if (r->%s != r->%s) {\n" field1 field2;
5994               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5995                 test_name field1 field2;
5996               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5997               pr "      return -1;\n";
5998               pr "    }\n"
5999           | CompareFieldsStrEq (field1, field2) ->
6000               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
6001               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6002                 test_name field1 field2;
6003               pr "               r->%s, r->%s);\n" field1 field2;
6004               pr "      return -1;\n";
6005               pr "    }\n"
6006         ) checks
6007       in
6008       List.iter (generate_test_command_call test_name) seq;
6009       generate_test_command_call ~test test_name last
6010   | TestLastFail seq ->
6011       pr "  /* TestLastFail for %s (%d) */\n" name i;
6012       let seq, last = get_seq_last seq in
6013       List.iter (generate_test_command_call test_name) seq;
6014       generate_test_command_call test_name ~expect_error:true last
6015
6016 (* Generate the code to run a command, leaving the result in 'r'.
6017  * If you expect to get an error then you should set expect_error:true.
6018  *)
6019 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6020   match cmd with
6021   | [] -> assert false
6022   | name :: args ->
6023       (* Look up the command to find out what args/ret it has. *)
6024       let style =
6025         try
6026           let _, style, _, _, _, _, _ =
6027             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6028           style
6029         with Not_found ->
6030           failwithf "%s: in test, command %s was not found" test_name name in
6031
6032       if List.length (snd style) <> List.length args then
6033         failwithf "%s: in test, wrong number of args given to %s"
6034           test_name name;
6035
6036       pr "  {\n";
6037
6038       List.iter (
6039         function
6040         | OptString n, "NULL" -> ()
6041         | Pathname n, arg
6042         | Device n, arg
6043         | Dev_or_Path n, arg
6044         | String n, arg
6045         | OptString n, arg ->
6046             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6047         | Int _, _
6048         | Bool _, _
6049         | FileIn _, _ | FileOut _, _ -> ()
6050         | StringList n, arg | DeviceList n, arg ->
6051             let strs = string_split " " arg in
6052             iteri (
6053               fun i str ->
6054                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6055             ) strs;
6056             pr "    const char *const %s[] = {\n" n;
6057             iteri (
6058               fun i _ -> pr "      %s_%d,\n" n i
6059             ) strs;
6060             pr "      NULL\n";
6061             pr "    };\n";
6062       ) (List.combine (snd style) args);
6063
6064       let error_code =
6065         match fst style with
6066         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6067         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6068         | RConstString _ | RConstOptString _ ->
6069             pr "    const char *r;\n"; "NULL"
6070         | RString _ -> pr "    char *r;\n"; "NULL"
6071         | RStringList _ | RHashtable _ ->
6072             pr "    char **r;\n";
6073             pr "    int i;\n";
6074             "NULL"
6075         | RStruct (_, typ) ->
6076             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6077         | RStructList (_, typ) ->
6078             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6079         | RBufferOut _ ->
6080             pr "    char *r;\n";
6081             pr "    size_t size;\n";
6082             "NULL" in
6083
6084       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6085       pr "    r = guestfs_%s (g" name;
6086
6087       (* Generate the parameters. *)
6088       List.iter (
6089         function
6090         | OptString _, "NULL" -> pr ", NULL"
6091         | Pathname n, _
6092         | Device n, _ | Dev_or_Path n, _
6093         | String n, _
6094         | OptString n, _ ->
6095             pr ", %s" n
6096         | FileIn _, arg | FileOut _, arg ->
6097             pr ", \"%s\"" (c_quote arg)
6098         | StringList n, _ | DeviceList n, _ ->
6099             pr ", (char **) %s" n
6100         | Int _, arg ->
6101             let i =
6102               try int_of_string arg
6103               with Failure "int_of_string" ->
6104                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6105             pr ", %d" i
6106         | Bool _, arg ->
6107             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6108       ) (List.combine (snd style) args);
6109
6110       (match fst style with
6111        | RBufferOut _ -> pr ", &size"
6112        | _ -> ()
6113       );
6114
6115       pr ");\n";
6116
6117       if not expect_error then
6118         pr "    if (r == %s)\n" error_code
6119       else
6120         pr "    if (r != %s)\n" error_code;
6121       pr "      return -1;\n";
6122
6123       (* Insert the test code. *)
6124       (match test with
6125        | None -> ()
6126        | Some f -> f ()
6127       );
6128
6129       (match fst style with
6130        | RErr | RInt _ | RInt64 _ | RBool _
6131        | RConstString _ | RConstOptString _ -> ()
6132        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6133        | RStringList _ | RHashtable _ ->
6134            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6135            pr "      free (r[i]);\n";
6136            pr "    free (r);\n"
6137        | RStruct (_, typ) ->
6138            pr "    guestfs_free_%s (r);\n" typ
6139        | RStructList (_, typ) ->
6140            pr "    guestfs_free_%s_list (r);\n" typ
6141       );
6142
6143       pr "  }\n"
6144
6145 and c_quote str =
6146   let str = replace_str str "\r" "\\r" in
6147   let str = replace_str str "\n" "\\n" in
6148   let str = replace_str str "\t" "\\t" in
6149   let str = replace_str str "\000" "\\0" in
6150   str
6151
6152 (* Generate a lot of different functions for guestfish. *)
6153 and generate_fish_cmds () =
6154   generate_header CStyle GPLv2;
6155
6156   let all_functions =
6157     List.filter (
6158       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6159     ) all_functions in
6160   let all_functions_sorted =
6161     List.filter (
6162       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6163     ) all_functions_sorted in
6164
6165   pr "#include <stdio.h>\n";
6166   pr "#include <stdlib.h>\n";
6167   pr "#include <string.h>\n";
6168   pr "#include <inttypes.h>\n";
6169   pr "\n";
6170   pr "#include <guestfs.h>\n";
6171   pr "#include \"c-ctype.h\"\n";
6172   pr "#include \"fish.h\"\n";
6173   pr "\n";
6174
6175   (* list_commands function, which implements guestfish -h *)
6176   pr "void list_commands (void)\n";
6177   pr "{\n";
6178   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6179   pr "  list_builtin_commands ();\n";
6180   List.iter (
6181     fun (name, _, _, flags, _, shortdesc, _) ->
6182       let name = replace_char name '_' '-' in
6183       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6184         name shortdesc
6185   ) all_functions_sorted;
6186   pr "  printf (\"    %%s\\n\",";
6187   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6188   pr "}\n";
6189   pr "\n";
6190
6191   (* display_command function, which implements guestfish -h cmd *)
6192   pr "void display_command (const char *cmd)\n";
6193   pr "{\n";
6194   List.iter (
6195     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6196       let name2 = replace_char name '_' '-' in
6197       let alias =
6198         try find_map (function FishAlias n -> Some n | _ -> None) flags
6199         with Not_found -> name in
6200       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6201       let synopsis =
6202         match snd style with
6203         | [] -> name2
6204         | args ->
6205             sprintf "%s <%s>"
6206               name2 (String.concat "> <" (List.map name_of_argt args)) in
6207
6208       let warnings =
6209         if List.mem ProtocolLimitWarning flags then
6210           ("\n\n" ^ protocol_limit_warning)
6211         else "" in
6212
6213       (* For DangerWillRobinson commands, we should probably have
6214        * guestfish prompt before allowing you to use them (especially
6215        * in interactive mode). XXX
6216        *)
6217       let warnings =
6218         warnings ^
6219           if List.mem DangerWillRobinson flags then
6220             ("\n\n" ^ danger_will_robinson)
6221           else "" in
6222
6223       let warnings =
6224         warnings ^
6225           match deprecation_notice flags with
6226           | None -> ""
6227           | Some txt -> "\n\n" ^ txt in
6228
6229       let describe_alias =
6230         if name <> alias then
6231           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6232         else "" in
6233
6234       pr "  if (";
6235       pr "strcasecmp (cmd, \"%s\") == 0" name;
6236       if name <> name2 then
6237         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6238       if name <> alias then
6239         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6240       pr ")\n";
6241       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6242         name2 shortdesc
6243         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6244       pr "  else\n"
6245   ) all_functions;
6246   pr "    display_builtin_command (cmd);\n";
6247   pr "}\n";
6248   pr "\n";
6249
6250   let emit_print_list_function typ =
6251     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6252       typ typ typ;
6253     pr "{\n";
6254     pr "  unsigned int i;\n";
6255     pr "\n";
6256     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6257     pr "    printf (\"[%%d] = {\\n\", i);\n";
6258     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6259     pr "    printf (\"}\\n\");\n";
6260     pr "  }\n";
6261     pr "}\n";
6262     pr "\n";
6263   in
6264
6265   (* print_* functions *)
6266   List.iter (
6267     fun (typ, cols) ->
6268       let needs_i =
6269         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6270
6271       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6272       pr "{\n";
6273       if needs_i then (
6274         pr "  unsigned int i;\n";
6275         pr "\n"
6276       );
6277       List.iter (
6278         function
6279         | name, FString ->
6280             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6281         | name, FUUID ->
6282             pr "  printf (\"%s: \");\n" name;
6283             pr "  for (i = 0; i < 32; ++i)\n";
6284             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6285             pr "  printf (\"\\n\");\n"
6286         | name, FBuffer ->
6287             pr "  printf (\"%%s%s: \", indent);\n" name;
6288             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6289             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6290             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6291             pr "    else\n";
6292             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6293             pr "  printf (\"\\n\");\n"
6294         | name, (FUInt64|FBytes) ->
6295             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6296               name typ name
6297         | name, FInt64 ->
6298             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6299               name typ name
6300         | name, FUInt32 ->
6301             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6302               name typ name
6303         | name, FInt32 ->
6304             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6305               name typ name
6306         | name, FChar ->
6307             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6308               name typ name
6309         | name, FOptPercent ->
6310             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6311               typ name name typ name;
6312             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6313       ) cols;
6314       pr "}\n";
6315       pr "\n";
6316   ) structs;
6317
6318   (* Emit a print_TYPE_list function definition only if that function is used. *)
6319   List.iter (
6320     function
6321     | typ, (RStructListOnly | RStructAndList) ->
6322         (* generate the function for typ *)
6323         emit_print_list_function typ
6324     | typ, _ -> () (* empty *)
6325   ) rstructs_used;
6326
6327   (* Emit a print_TYPE function definition only if that function is used. *)
6328   List.iter (
6329     function
6330     | typ, RStructOnly ->
6331         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6332         pr "{\n";
6333         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6334         pr "}\n";
6335         pr "\n";
6336     | typ, _ -> () (* empty *)
6337   ) rstructs_used;
6338
6339   (* run_<action> actions *)
6340   List.iter (
6341     fun (name, style, _, flags, _, _, _) ->
6342       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6343       pr "{\n";
6344       (match fst style with
6345        | RErr
6346        | RInt _
6347        | RBool _ -> pr "  int r;\n"
6348        | RInt64 _ -> pr "  int64_t r;\n"
6349        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6350        | RString _ -> pr "  char *r;\n"
6351        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6352        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6353        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6354        | RBufferOut _ ->
6355            pr "  char *r;\n";
6356            pr "  size_t size;\n";
6357       );
6358       List.iter (
6359         function
6360         | Pathname n
6361         | Device n | Dev_or_Path n
6362         | String n
6363         | OptString n
6364         | FileIn n
6365         | FileOut n -> pr "  const char *%s;\n" n
6366         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6367         | Bool n -> pr "  int %s;\n" n
6368         | Int n -> pr "  int %s;\n" n
6369       ) (snd style);
6370
6371       (* Check and convert parameters. *)
6372       let argc_expected = List.length (snd style) in
6373       pr "  if (argc != %d) {\n" argc_expected;
6374       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6375         argc_expected;
6376       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6377       pr "    return -1;\n";
6378       pr "  }\n";
6379       iteri (
6380         fun i ->
6381           function
6382           | Pathname name
6383           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6384           | OptString name ->
6385               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6386                 name i i
6387           | FileIn name ->
6388               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6389                 name i i
6390           | FileOut name ->
6391               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6392                 name i i
6393           | StringList name | DeviceList name ->
6394               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6395               pr "  if (%s == NULL) return -1;\n" name;
6396           | Bool name ->
6397               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6398           | Int name ->
6399               pr "  %s = atoi (argv[%d]);\n" name i
6400       ) (snd style);
6401
6402       (* Call C API function. *)
6403       let fn =
6404         try find_map (function FishAction n -> Some n | _ -> None) flags
6405         with Not_found -> sprintf "guestfs_%s" name in
6406       pr "  r = %s " fn;
6407       generate_c_call_args ~handle:"g" style;
6408       pr ";\n";
6409
6410       List.iter (
6411         function
6412         | Pathname name | Device name | Dev_or_Path name | String name
6413         | OptString name | FileIn name | FileOut name | Bool name
6414         | Int name -> ()
6415         | StringList name | DeviceList name ->
6416             pr "  free_strings (%s);\n" name
6417       ) (snd style);
6418
6419       (* Check return value for errors and display command results. *)
6420       (match fst style with
6421        | RErr -> pr "  return r;\n"
6422        | RInt _ ->
6423            pr "  if (r == -1) return -1;\n";
6424            pr "  printf (\"%%d\\n\", r);\n";
6425            pr "  return 0;\n"
6426        | RInt64 _ ->
6427            pr "  if (r == -1) return -1;\n";
6428            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6429            pr "  return 0;\n"
6430        | RBool _ ->
6431            pr "  if (r == -1) return -1;\n";
6432            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6433            pr "  return 0;\n"
6434        | RConstString _ ->
6435            pr "  if (r == NULL) return -1;\n";
6436            pr "  printf (\"%%s\\n\", r);\n";
6437            pr "  return 0;\n"
6438        | RConstOptString _ ->
6439            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6440            pr "  return 0;\n"
6441        | RString _ ->
6442            pr "  if (r == NULL) return -1;\n";
6443            pr "  printf (\"%%s\\n\", r);\n";
6444            pr "  free (r);\n";
6445            pr "  return 0;\n"
6446        | RStringList _ ->
6447            pr "  if (r == NULL) return -1;\n";
6448            pr "  print_strings (r);\n";
6449            pr "  free_strings (r);\n";
6450            pr "  return 0;\n"
6451        | RStruct (_, typ) ->
6452            pr "  if (r == NULL) return -1;\n";
6453            pr "  print_%s (r);\n" typ;
6454            pr "  guestfs_free_%s (r);\n" typ;
6455            pr "  return 0;\n"
6456        | RStructList (_, typ) ->
6457            pr "  if (r == NULL) return -1;\n";
6458            pr "  print_%s_list (r);\n" typ;
6459            pr "  guestfs_free_%s_list (r);\n" typ;
6460            pr "  return 0;\n"
6461        | RHashtable _ ->
6462            pr "  if (r == NULL) return -1;\n";
6463            pr "  print_table (r);\n";
6464            pr "  free_strings (r);\n";
6465            pr "  return 0;\n"
6466        | RBufferOut _ ->
6467            pr "  if (r == NULL) return -1;\n";
6468            pr "  fwrite (r, size, 1, stdout);\n";
6469            pr "  free (r);\n";
6470            pr "  return 0;\n"
6471       );
6472       pr "}\n";
6473       pr "\n"
6474   ) all_functions;
6475
6476   (* run_action function *)
6477   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6478   pr "{\n";
6479   List.iter (
6480     fun (name, _, _, flags, _, _, _) ->
6481       let name2 = replace_char name '_' '-' in
6482       let alias =
6483         try find_map (function FishAlias n -> Some n | _ -> None) flags
6484         with Not_found -> name in
6485       pr "  if (";
6486       pr "strcasecmp (cmd, \"%s\") == 0" name;
6487       if name <> name2 then
6488         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6489       if name <> alias then
6490         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6491       pr ")\n";
6492       pr "    return run_%s (cmd, argc, argv);\n" name;
6493       pr "  else\n";
6494   ) all_functions;
6495   pr "    {\n";
6496   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6497   pr "      return -1;\n";
6498   pr "    }\n";
6499   pr "  return 0;\n";
6500   pr "}\n";
6501   pr "\n"
6502
6503 (* Readline completion for guestfish. *)
6504 and generate_fish_completion () =
6505   generate_header CStyle GPLv2;
6506
6507   let all_functions =
6508     List.filter (
6509       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6510     ) all_functions in
6511
6512   pr "\
6513 #include <config.h>
6514
6515 #include <stdio.h>
6516 #include <stdlib.h>
6517 #include <string.h>
6518
6519 #ifdef HAVE_LIBREADLINE
6520 #include <readline/readline.h>
6521 #endif
6522
6523 #include \"fish.h\"
6524
6525 #ifdef HAVE_LIBREADLINE
6526
6527 static const char *const commands[] = {
6528   BUILTIN_COMMANDS_FOR_COMPLETION,
6529 ";
6530
6531   (* Get the commands, including the aliases.  They don't need to be
6532    * sorted - the generator() function just does a dumb linear search.
6533    *)
6534   let commands =
6535     List.map (
6536       fun (name, _, _, flags, _, _, _) ->
6537         let name2 = replace_char name '_' '-' in
6538         let alias =
6539           try find_map (function FishAlias n -> Some n | _ -> None) flags
6540           with Not_found -> name in
6541
6542         if name <> alias then [name2; alias] else [name2]
6543     ) all_functions in
6544   let commands = List.flatten commands in
6545
6546   List.iter (pr "  \"%s\",\n") commands;
6547
6548   pr "  NULL
6549 };
6550
6551 static char *
6552 generator (const char *text, int state)
6553 {
6554   static int index, len;
6555   const char *name;
6556
6557   if (!state) {
6558     index = 0;
6559     len = strlen (text);
6560   }
6561
6562   rl_attempted_completion_over = 1;
6563
6564   while ((name = commands[index]) != NULL) {
6565     index++;
6566     if (strncasecmp (name, text, len) == 0)
6567       return strdup (name);
6568   }
6569
6570   return NULL;
6571 }
6572
6573 #endif /* HAVE_LIBREADLINE */
6574
6575 char **do_completion (const char *text, int start, int end)
6576 {
6577   char **matches = NULL;
6578
6579 #ifdef HAVE_LIBREADLINE
6580   rl_completion_append_character = ' ';
6581
6582   if (start == 0)
6583     matches = rl_completion_matches (text, generator);
6584   else if (complete_dest_paths)
6585     matches = rl_completion_matches (text, complete_dest_paths_generator);
6586 #endif
6587
6588   return matches;
6589 }
6590 ";
6591
6592 (* Generate the POD documentation for guestfish. *)
6593 and generate_fish_actions_pod () =
6594   let all_functions_sorted =
6595     List.filter (
6596       fun (_, _, _, flags, _, _, _) ->
6597         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6598     ) all_functions_sorted in
6599
6600   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6601
6602   List.iter (
6603     fun (name, style, _, flags, _, _, longdesc) ->
6604       let longdesc =
6605         Str.global_substitute rex (
6606           fun s ->
6607             let sub =
6608               try Str.matched_group 1 s
6609               with Not_found ->
6610                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6611             "C<" ^ replace_char sub '_' '-' ^ ">"
6612         ) longdesc in
6613       let name = replace_char name '_' '-' in
6614       let alias =
6615         try find_map (function FishAlias n -> Some n | _ -> None) flags
6616         with Not_found -> name in
6617
6618       pr "=head2 %s" name;
6619       if name <> alias then
6620         pr " | %s" alias;
6621       pr "\n";
6622       pr "\n";
6623       pr " %s" name;
6624       List.iter (
6625         function
6626         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6627         | OptString n -> pr " %s" n
6628         | StringList n | DeviceList n -> pr " '%s ...'" n
6629         | Bool _ -> pr " true|false"
6630         | Int n -> pr " %s" n
6631         | FileIn n | FileOut n -> pr " (%s|-)" n
6632       ) (snd style);
6633       pr "\n";
6634       pr "\n";
6635       pr "%s\n\n" longdesc;
6636
6637       if List.exists (function FileIn _ | FileOut _ -> true
6638                       | _ -> false) (snd style) then
6639         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6640
6641       if List.mem ProtocolLimitWarning flags then
6642         pr "%s\n\n" protocol_limit_warning;
6643
6644       if List.mem DangerWillRobinson flags then
6645         pr "%s\n\n" danger_will_robinson;
6646
6647       match deprecation_notice flags with
6648       | None -> ()
6649       | Some txt -> pr "%s\n\n" txt
6650   ) all_functions_sorted
6651
6652 (* Generate a C function prototype. *)
6653 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6654     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6655     ?(prefix = "")
6656     ?handle name style =
6657   if extern then pr "extern ";
6658   if static then pr "static ";
6659   (match fst style with
6660    | RErr -> pr "int "
6661    | RInt _ -> pr "int "
6662    | RInt64 _ -> pr "int64_t "
6663    | RBool _ -> pr "int "
6664    | RConstString _ | RConstOptString _ -> pr "const char *"
6665    | RString _ | RBufferOut _ -> pr "char *"
6666    | RStringList _ | RHashtable _ -> pr "char **"
6667    | RStruct (_, typ) ->
6668        if not in_daemon then pr "struct guestfs_%s *" typ
6669        else pr "guestfs_int_%s *" typ
6670    | RStructList (_, typ) ->
6671        if not in_daemon then pr "struct guestfs_%s_list *" typ
6672        else pr "guestfs_int_%s_list *" typ
6673   );
6674   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6675   pr "%s%s (" prefix name;
6676   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6677     pr "void"
6678   else (
6679     let comma = ref false in
6680     (match handle with
6681      | None -> ()
6682      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6683     );
6684     let next () =
6685       if !comma then (
6686         if single_line then pr ", " else pr ",\n\t\t"
6687       );
6688       comma := true
6689     in
6690     List.iter (
6691       function
6692       | Pathname n
6693       | Device n | Dev_or_Path n
6694       | String n
6695       | OptString n ->
6696           next ();
6697           pr "const char *%s" n
6698       | StringList n | DeviceList n ->
6699           next ();
6700           pr "char *const *%s" n
6701       | Bool n -> next (); pr "int %s" n
6702       | Int n -> next (); pr "int %s" n
6703       | FileIn n
6704       | FileOut n ->
6705           if not in_daemon then (next (); pr "const char *%s" n)
6706     ) (snd style);
6707     if is_RBufferOut then (next (); pr "size_t *size_r");
6708   );
6709   pr ")";
6710   if semicolon then pr ";";
6711   if newline then pr "\n"
6712
6713 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6714 and generate_c_call_args ?handle ?(decl = false) style =
6715   pr "(";
6716   let comma = ref false in
6717   let next () =
6718     if !comma then pr ", ";
6719     comma := true
6720   in
6721   (match handle with
6722    | None -> ()
6723    | Some handle -> pr "%s" handle; comma := true
6724   );
6725   List.iter (
6726     fun arg ->
6727       next ();
6728       pr "%s" (name_of_argt arg)
6729   ) (snd style);
6730   (* For RBufferOut calls, add implicit &size parameter. *)
6731   if not decl then (
6732     match fst style with
6733     | RBufferOut _ ->
6734         next ();
6735         pr "&size"
6736     | _ -> ()
6737   );
6738   pr ")"
6739
6740 (* Generate the OCaml bindings interface. *)
6741 and generate_ocaml_mli () =
6742   generate_header OCamlStyle LGPLv2;
6743
6744   pr "\
6745 (** For API documentation you should refer to the C API
6746     in the guestfs(3) manual page.  The OCaml API uses almost
6747     exactly the same calls. *)
6748
6749 type t
6750 (** A [guestfs_h] handle. *)
6751
6752 exception Error of string
6753 (** This exception is raised when there is an error. *)
6754
6755 val create : unit -> t
6756
6757 val close : t -> unit
6758 (** Handles are closed by the garbage collector when they become
6759     unreferenced, but callers can also call this in order to
6760     provide predictable cleanup. *)
6761
6762 ";
6763   generate_ocaml_structure_decls ();
6764
6765   (* The actions. *)
6766   List.iter (
6767     fun (name, style, _, _, _, shortdesc, _) ->
6768       generate_ocaml_prototype name style;
6769       pr "(** %s *)\n" shortdesc;
6770       pr "\n"
6771   ) all_functions
6772
6773 (* Generate the OCaml bindings implementation. *)
6774 and generate_ocaml_ml () =
6775   generate_header OCamlStyle LGPLv2;
6776
6777   pr "\
6778 type t
6779 exception Error of string
6780 external create : unit -> t = \"ocaml_guestfs_create\"
6781 external close : t -> unit = \"ocaml_guestfs_close\"
6782
6783 let () =
6784   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6785
6786 ";
6787
6788   generate_ocaml_structure_decls ();
6789
6790   (* The actions. *)
6791   List.iter (
6792     fun (name, style, _, _, _, shortdesc, _) ->
6793       generate_ocaml_prototype ~is_external:true name style;
6794   ) all_functions
6795
6796 (* Generate the OCaml bindings C implementation. *)
6797 and generate_ocaml_c () =
6798   generate_header CStyle LGPLv2;
6799
6800   pr "\
6801 #include <stdio.h>
6802 #include <stdlib.h>
6803 #include <string.h>
6804
6805 #include <caml/config.h>
6806 #include <caml/alloc.h>
6807 #include <caml/callback.h>
6808 #include <caml/fail.h>
6809 #include <caml/memory.h>
6810 #include <caml/mlvalues.h>
6811 #include <caml/signals.h>
6812
6813 #include <guestfs.h>
6814
6815 #include \"guestfs_c.h\"
6816
6817 /* Copy a hashtable of string pairs into an assoc-list.  We return
6818  * the list in reverse order, but hashtables aren't supposed to be
6819  * ordered anyway.
6820  */
6821 static CAMLprim value
6822 copy_table (char * const * argv)
6823 {
6824   CAMLparam0 ();
6825   CAMLlocal5 (rv, pairv, kv, vv, cons);
6826   int i;
6827
6828   rv = Val_int (0);
6829   for (i = 0; argv[i] != NULL; i += 2) {
6830     kv = caml_copy_string (argv[i]);
6831     vv = caml_copy_string (argv[i+1]);
6832     pairv = caml_alloc (2, 0);
6833     Store_field (pairv, 0, kv);
6834     Store_field (pairv, 1, vv);
6835     cons = caml_alloc (2, 0);
6836     Store_field (cons, 1, rv);
6837     rv = cons;
6838     Store_field (cons, 0, pairv);
6839   }
6840
6841   CAMLreturn (rv);
6842 }
6843
6844 ";
6845
6846   (* Struct copy functions. *)
6847
6848   let emit_ocaml_copy_list_function typ =
6849     pr "static CAMLprim value\n";
6850     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6851     pr "{\n";
6852     pr "  CAMLparam0 ();\n";
6853     pr "  CAMLlocal2 (rv, v);\n";
6854     pr "  unsigned int i;\n";
6855     pr "\n";
6856     pr "  if (%ss->len == 0)\n" typ;
6857     pr "    CAMLreturn (Atom (0));\n";
6858     pr "  else {\n";
6859     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6860     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6861     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6862     pr "      caml_modify (&Field (rv, i), v);\n";
6863     pr "    }\n";
6864     pr "    CAMLreturn (rv);\n";
6865     pr "  }\n";
6866     pr "}\n";
6867     pr "\n";
6868   in
6869
6870   List.iter (
6871     fun (typ, cols) ->
6872       let has_optpercent_col =
6873         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6874
6875       pr "static CAMLprim value\n";
6876       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6877       pr "{\n";
6878       pr "  CAMLparam0 ();\n";
6879       if has_optpercent_col then
6880         pr "  CAMLlocal3 (rv, v, v2);\n"
6881       else
6882         pr "  CAMLlocal2 (rv, v);\n";
6883       pr "\n";
6884       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6885       iteri (
6886         fun i col ->
6887           (match col with
6888            | name, FString ->
6889                pr "  v = caml_copy_string (%s->%s);\n" typ name
6890            | name, FBuffer ->
6891                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6892                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6893                  typ name typ name
6894            | name, FUUID ->
6895                pr "  v = caml_alloc_string (32);\n";
6896                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6897            | name, (FBytes|FInt64|FUInt64) ->
6898                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6899            | name, (FInt32|FUInt32) ->
6900                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6901            | name, FOptPercent ->
6902                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6903                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6904                pr "    v = caml_alloc (1, 0);\n";
6905                pr "    Store_field (v, 0, v2);\n";
6906                pr "  } else /* None */\n";
6907                pr "    v = Val_int (0);\n";
6908            | name, FChar ->
6909                pr "  v = Val_int (%s->%s);\n" typ name
6910           );
6911           pr "  Store_field (rv, %d, v);\n" i
6912       ) cols;
6913       pr "  CAMLreturn (rv);\n";
6914       pr "}\n";
6915       pr "\n";
6916   ) structs;
6917
6918   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6919   List.iter (
6920     function
6921     | typ, (RStructListOnly | RStructAndList) ->
6922         (* generate the function for typ *)
6923         emit_ocaml_copy_list_function typ
6924     | typ, _ -> () (* empty *)
6925   ) rstructs_used;
6926
6927   (* The wrappers. *)
6928   List.iter (
6929     fun (name, style, _, _, _, _, _) ->
6930       let params =
6931         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6932
6933       let needs_extra_vs =
6934         match fst style with RConstOptString _ -> true | _ -> false in
6935
6936       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6937       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6938       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6939
6940       pr "CAMLprim value\n";
6941       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6942       List.iter (pr ", value %s") (List.tl params);
6943       pr ")\n";
6944       pr "{\n";
6945
6946       (match params with
6947        | [p1; p2; p3; p4; p5] ->
6948            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6949        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6950            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6951            pr "  CAMLxparam%d (%s);\n"
6952              (List.length rest) (String.concat ", " rest)
6953        | ps ->
6954            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6955       );
6956       if not needs_extra_vs then
6957         pr "  CAMLlocal1 (rv);\n"
6958       else
6959         pr "  CAMLlocal3 (rv, v, v2);\n";
6960       pr "\n";
6961
6962       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6963       pr "  if (g == NULL)\n";
6964       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6965       pr "\n";
6966
6967       List.iter (
6968         function
6969         | Pathname n
6970         | Device n | Dev_or_Path n
6971         | String n
6972         | FileIn n
6973         | FileOut n ->
6974             pr "  const char *%s = String_val (%sv);\n" n n
6975         | OptString n ->
6976             pr "  const char *%s =\n" n;
6977             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6978               n n
6979         | StringList n | DeviceList n ->
6980             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6981         | Bool n ->
6982             pr "  int %s = Bool_val (%sv);\n" n n
6983         | Int n ->
6984             pr "  int %s = Int_val (%sv);\n" n n
6985       ) (snd style);
6986       let error_code =
6987         match fst style with
6988         | RErr -> pr "  int r;\n"; "-1"
6989         | RInt _ -> pr "  int r;\n"; "-1"
6990         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6991         | RBool _ -> pr "  int r;\n"; "-1"
6992         | RConstString _ | RConstOptString _ ->
6993             pr "  const char *r;\n"; "NULL"
6994         | RString _ -> pr "  char *r;\n"; "NULL"
6995         | RStringList _ ->
6996             pr "  int i;\n";
6997             pr "  char **r;\n";
6998             "NULL"
6999         | RStruct (_, typ) ->
7000             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7001         | RStructList (_, typ) ->
7002             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7003         | RHashtable _ ->
7004             pr "  int i;\n";
7005             pr "  char **r;\n";
7006             "NULL"
7007         | RBufferOut _ ->
7008             pr "  char *r;\n";
7009             pr "  size_t size;\n";
7010             "NULL" in
7011       pr "\n";
7012
7013       pr "  caml_enter_blocking_section ();\n";
7014       pr "  r = guestfs_%s " name;
7015       generate_c_call_args ~handle:"g" style;
7016       pr ";\n";
7017       pr "  caml_leave_blocking_section ();\n";
7018
7019       List.iter (
7020         function
7021         | StringList n | DeviceList n ->
7022             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7023         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7024         | FileIn _ | FileOut _ -> ()
7025       ) (snd style);
7026
7027       pr "  if (r == %s)\n" error_code;
7028       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7029       pr "\n";
7030
7031       (match fst style with
7032        | RErr -> pr "  rv = Val_unit;\n"
7033        | RInt _ -> pr "  rv = Val_int (r);\n"
7034        | RInt64 _ ->
7035            pr "  rv = caml_copy_int64 (r);\n"
7036        | RBool _ -> pr "  rv = Val_bool (r);\n"
7037        | RConstString _ ->
7038            pr "  rv = caml_copy_string (r);\n"
7039        | RConstOptString _ ->
7040            pr "  if (r) { /* Some string */\n";
7041            pr "    v = caml_alloc (1, 0);\n";
7042            pr "    v2 = caml_copy_string (r);\n";
7043            pr "    Store_field (v, 0, v2);\n";
7044            pr "  } else /* None */\n";
7045            pr "    v = Val_int (0);\n";
7046        | RString _ ->
7047            pr "  rv = caml_copy_string (r);\n";
7048            pr "  free (r);\n"
7049        | RStringList _ ->
7050            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7051            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7052            pr "  free (r);\n"
7053        | RStruct (_, typ) ->
7054            pr "  rv = copy_%s (r);\n" typ;
7055            pr "  guestfs_free_%s (r);\n" typ;
7056        | RStructList (_, typ) ->
7057            pr "  rv = copy_%s_list (r);\n" typ;
7058            pr "  guestfs_free_%s_list (r);\n" typ;
7059        | RHashtable _ ->
7060            pr "  rv = copy_table (r);\n";
7061            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7062            pr "  free (r);\n";
7063        | RBufferOut _ ->
7064            pr "  rv = caml_alloc_string (size);\n";
7065            pr "  memcpy (String_val (rv), r, size);\n";
7066       );
7067
7068       pr "  CAMLreturn (rv);\n";
7069       pr "}\n";
7070       pr "\n";
7071
7072       if List.length params > 5 then (
7073         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7074         pr "CAMLprim value ";
7075         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7076         pr "CAMLprim value\n";
7077         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7078         pr "{\n";
7079         pr "  return ocaml_guestfs_%s (argv[0]" name;
7080         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7081         pr ");\n";
7082         pr "}\n";
7083         pr "\n"
7084       )
7085   ) all_functions
7086
7087 and generate_ocaml_structure_decls () =
7088   List.iter (
7089     fun (typ, cols) ->
7090       pr "type %s = {\n" typ;
7091       List.iter (
7092         function
7093         | name, FString -> pr "  %s : string;\n" name
7094         | name, FBuffer -> pr "  %s : string;\n" name
7095         | name, FUUID -> pr "  %s : string;\n" name
7096         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7097         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7098         | name, FChar -> pr "  %s : char;\n" name
7099         | name, FOptPercent -> pr "  %s : float option;\n" name
7100       ) cols;
7101       pr "}\n";
7102       pr "\n"
7103   ) structs
7104
7105 and generate_ocaml_prototype ?(is_external = false) name style =
7106   if is_external then pr "external " else pr "val ";
7107   pr "%s : t -> " name;
7108   List.iter (
7109     function
7110     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7111     | OptString _ -> pr "string option -> "
7112     | StringList _ | DeviceList _ -> pr "string array -> "
7113     | Bool _ -> pr "bool -> "
7114     | Int _ -> pr "int -> "
7115   ) (snd style);
7116   (match fst style with
7117    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7118    | RInt _ -> pr "int"
7119    | RInt64 _ -> pr "int64"
7120    | RBool _ -> pr "bool"
7121    | RConstString _ -> pr "string"
7122    | RConstOptString _ -> pr "string option"
7123    | RString _ | RBufferOut _ -> pr "string"
7124    | RStringList _ -> pr "string array"
7125    | RStruct (_, typ) -> pr "%s" typ
7126    | RStructList (_, typ) -> pr "%s array" typ
7127    | RHashtable _ -> pr "(string * string) list"
7128   );
7129   if is_external then (
7130     pr " = ";
7131     if List.length (snd style) + 1 > 5 then
7132       pr "\"ocaml_guestfs_%s_byte\" " name;
7133     pr "\"ocaml_guestfs_%s\"" name
7134   );
7135   pr "\n"
7136
7137 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7138 and generate_perl_xs () =
7139   generate_header CStyle LGPLv2;
7140
7141   pr "\
7142 #include \"EXTERN.h\"
7143 #include \"perl.h\"
7144 #include \"XSUB.h\"
7145
7146 #include <guestfs.h>
7147
7148 #ifndef PRId64
7149 #define PRId64 \"lld\"
7150 #endif
7151
7152 static SV *
7153 my_newSVll(long long val) {
7154 #ifdef USE_64_BIT_ALL
7155   return newSViv(val);
7156 #else
7157   char buf[100];
7158   int len;
7159   len = snprintf(buf, 100, \"%%\" PRId64, val);
7160   return newSVpv(buf, len);
7161 #endif
7162 }
7163
7164 #ifndef PRIu64
7165 #define PRIu64 \"llu\"
7166 #endif
7167
7168 static SV *
7169 my_newSVull(unsigned long long val) {
7170 #ifdef USE_64_BIT_ALL
7171   return newSVuv(val);
7172 #else
7173   char buf[100];
7174   int len;
7175   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7176   return newSVpv(buf, len);
7177 #endif
7178 }
7179
7180 /* http://www.perlmonks.org/?node_id=680842 */
7181 static char **
7182 XS_unpack_charPtrPtr (SV *arg) {
7183   char **ret;
7184   AV *av;
7185   I32 i;
7186
7187   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7188     croak (\"array reference expected\");
7189
7190   av = (AV *)SvRV (arg);
7191   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7192   if (!ret)
7193     croak (\"malloc failed\");
7194
7195   for (i = 0; i <= av_len (av); i++) {
7196     SV **elem = av_fetch (av, i, 0);
7197
7198     if (!elem || !*elem)
7199       croak (\"missing element in list\");
7200
7201     ret[i] = SvPV_nolen (*elem);
7202   }
7203
7204   ret[i] = NULL;
7205
7206   return ret;
7207 }
7208
7209 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7210
7211 PROTOTYPES: ENABLE
7212
7213 guestfs_h *
7214 _create ()
7215    CODE:
7216       RETVAL = guestfs_create ();
7217       if (!RETVAL)
7218         croak (\"could not create guestfs handle\");
7219       guestfs_set_error_handler (RETVAL, NULL, NULL);
7220  OUTPUT:
7221       RETVAL
7222
7223 void
7224 DESTROY (g)
7225       guestfs_h *g;
7226  PPCODE:
7227       guestfs_close (g);
7228
7229 ";
7230
7231   List.iter (
7232     fun (name, style, _, _, _, _, _) ->
7233       (match fst style with
7234        | RErr -> pr "void\n"
7235        | RInt _ -> pr "SV *\n"
7236        | RInt64 _ -> pr "SV *\n"
7237        | RBool _ -> pr "SV *\n"
7238        | RConstString _ -> pr "SV *\n"
7239        | RConstOptString _ -> pr "SV *\n"
7240        | RString _ -> pr "SV *\n"
7241        | RBufferOut _ -> pr "SV *\n"
7242        | RStringList _
7243        | RStruct _ | RStructList _
7244        | RHashtable _ ->
7245            pr "void\n" (* all lists returned implictly on the stack *)
7246       );
7247       (* Call and arguments. *)
7248       pr "%s " name;
7249       generate_c_call_args ~handle:"g" ~decl:true style;
7250       pr "\n";
7251       pr "      guestfs_h *g;\n";
7252       iteri (
7253         fun i ->
7254           function
7255           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7256               pr "      char *%s;\n" n
7257           | OptString n ->
7258               (* http://www.perlmonks.org/?node_id=554277
7259                * Note that the implicit handle argument means we have
7260                * to add 1 to the ST(x) operator.
7261                *)
7262               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7263           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7264           | Bool n -> pr "      int %s;\n" n
7265           | Int n -> pr "      int %s;\n" n
7266       ) (snd style);
7267
7268       let do_cleanups () =
7269         List.iter (
7270           function
7271           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7272           | FileIn _ | FileOut _ -> ()
7273           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7274         ) (snd style)
7275       in
7276
7277       (* Code. *)
7278       (match fst style with
7279        | RErr ->
7280            pr "PREINIT:\n";
7281            pr "      int r;\n";
7282            pr " PPCODE:\n";
7283            pr "      r = guestfs_%s " name;
7284            generate_c_call_args ~handle:"g" style;
7285            pr ";\n";
7286            do_cleanups ();
7287            pr "      if (r == -1)\n";
7288            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7289        | RInt n
7290        | RBool n ->
7291            pr "PREINIT:\n";
7292            pr "      int %s;\n" n;
7293            pr "   CODE:\n";
7294            pr "      %s = guestfs_%s " n name;
7295            generate_c_call_args ~handle:"g" style;
7296            pr ";\n";
7297            do_cleanups ();
7298            pr "      if (%s == -1)\n" n;
7299            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7300            pr "      RETVAL = newSViv (%s);\n" n;
7301            pr " OUTPUT:\n";
7302            pr "      RETVAL\n"
7303        | RInt64 n ->
7304            pr "PREINIT:\n";
7305            pr "      int64_t %s;\n" n;
7306            pr "   CODE:\n";
7307            pr "      %s = guestfs_%s " n name;
7308            generate_c_call_args ~handle:"g" style;
7309            pr ";\n";
7310            do_cleanups ();
7311            pr "      if (%s == -1)\n" n;
7312            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7313            pr "      RETVAL = my_newSVll (%s);\n" n;
7314            pr " OUTPUT:\n";
7315            pr "      RETVAL\n"
7316        | RConstString n ->
7317            pr "PREINIT:\n";
7318            pr "      const char *%s;\n" n;
7319            pr "   CODE:\n";
7320            pr "      %s = guestfs_%s " n name;
7321            generate_c_call_args ~handle:"g" style;
7322            pr ";\n";
7323            do_cleanups ();
7324            pr "      if (%s == NULL)\n" n;
7325            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7326            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7327            pr " OUTPUT:\n";
7328            pr "      RETVAL\n"
7329        | RConstOptString n ->
7330            pr "PREINIT:\n";
7331            pr "      const char *%s;\n" n;
7332            pr "   CODE:\n";
7333            pr "      %s = guestfs_%s " n name;
7334            generate_c_call_args ~handle:"g" style;
7335            pr ";\n";
7336            do_cleanups ();
7337            pr "      if (%s == NULL)\n" n;
7338            pr "        RETVAL = &PL_sv_undef;\n";
7339            pr "      else\n";
7340            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7341            pr " OUTPUT:\n";
7342            pr "      RETVAL\n"
7343        | RString n ->
7344            pr "PREINIT:\n";
7345            pr "      char *%s;\n" n;
7346            pr "   CODE:\n";
7347            pr "      %s = guestfs_%s " n name;
7348            generate_c_call_args ~handle:"g" style;
7349            pr ";\n";
7350            do_cleanups ();
7351            pr "      if (%s == NULL)\n" n;
7352            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7353            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7354            pr "      free (%s);\n" n;
7355            pr " OUTPUT:\n";
7356            pr "      RETVAL\n"
7357        | RStringList n | RHashtable n ->
7358            pr "PREINIT:\n";
7359            pr "      char **%s;\n" n;
7360            pr "      int i, n;\n";
7361            pr " PPCODE:\n";
7362            pr "      %s = guestfs_%s " n name;
7363            generate_c_call_args ~handle:"g" style;
7364            pr ";\n";
7365            do_cleanups ();
7366            pr "      if (%s == NULL)\n" n;
7367            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7368            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7369            pr "      EXTEND (SP, n);\n";
7370            pr "      for (i = 0; i < n; ++i) {\n";
7371            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7372            pr "        free (%s[i]);\n" n;
7373            pr "      }\n";
7374            pr "      free (%s);\n" n;
7375        | RStruct (n, typ) ->
7376            let cols = cols_of_struct typ in
7377            generate_perl_struct_code typ cols name style n do_cleanups
7378        | RStructList (n, typ) ->
7379            let cols = cols_of_struct typ in
7380            generate_perl_struct_list_code typ cols name style n do_cleanups
7381        | RBufferOut n ->
7382            pr "PREINIT:\n";
7383            pr "      char *%s;\n" n;
7384            pr "      size_t size;\n";
7385            pr "   CODE:\n";
7386            pr "      %s = guestfs_%s " n name;
7387            generate_c_call_args ~handle:"g" style;
7388            pr ";\n";
7389            do_cleanups ();
7390            pr "      if (%s == NULL)\n" n;
7391            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7392            pr "      RETVAL = newSVpv (%s, size);\n" n;
7393            pr "      free (%s);\n" n;
7394            pr " OUTPUT:\n";
7395            pr "      RETVAL\n"
7396       );
7397
7398       pr "\n"
7399   ) all_functions
7400
7401 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7402   pr "PREINIT:\n";
7403   pr "      struct guestfs_%s_list *%s;\n" typ n;
7404   pr "      int i;\n";
7405   pr "      HV *hv;\n";
7406   pr " PPCODE:\n";
7407   pr "      %s = guestfs_%s " n name;
7408   generate_c_call_args ~handle:"g" style;
7409   pr ";\n";
7410   do_cleanups ();
7411   pr "      if (%s == NULL)\n" n;
7412   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7413   pr "      EXTEND (SP, %s->len);\n" n;
7414   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7415   pr "        hv = newHV ();\n";
7416   List.iter (
7417     function
7418     | name, FString ->
7419         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7420           name (String.length name) n name
7421     | name, FUUID ->
7422         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7423           name (String.length name) n name
7424     | name, FBuffer ->
7425         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7426           name (String.length name) n name n name
7427     | name, (FBytes|FUInt64) ->
7428         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7429           name (String.length name) n name
7430     | name, FInt64 ->
7431         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7432           name (String.length name) n name
7433     | name, (FInt32|FUInt32) ->
7434         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7435           name (String.length name) n name
7436     | name, FChar ->
7437         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7438           name (String.length name) n name
7439     | name, FOptPercent ->
7440         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7441           name (String.length name) n name
7442   ) cols;
7443   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7444   pr "      }\n";
7445   pr "      guestfs_free_%s_list (%s);\n" typ n
7446
7447 and generate_perl_struct_code typ cols name style n do_cleanups =
7448   pr "PREINIT:\n";
7449   pr "      struct guestfs_%s *%s;\n" typ n;
7450   pr " PPCODE:\n";
7451   pr "      %s = guestfs_%s " n name;
7452   generate_c_call_args ~handle:"g" style;
7453   pr ";\n";
7454   do_cleanups ();
7455   pr "      if (%s == NULL)\n" n;
7456   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7457   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7458   List.iter (
7459     fun ((name, _) as col) ->
7460       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7461
7462       match col with
7463       | name, FString ->
7464           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7465             n name
7466       | name, FBuffer ->
7467           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7468             n name n name
7469       | name, FUUID ->
7470           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7471             n name
7472       | name, (FBytes|FUInt64) ->
7473           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7474             n name
7475       | name, FInt64 ->
7476           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7477             n name
7478       | name, (FInt32|FUInt32) ->
7479           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7480             n name
7481       | name, FChar ->
7482           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7483             n name
7484       | name, FOptPercent ->
7485           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7486             n name
7487   ) cols;
7488   pr "      free (%s);\n" n
7489
7490 (* Generate Sys/Guestfs.pm. *)
7491 and generate_perl_pm () =
7492   generate_header HashStyle LGPLv2;
7493
7494   pr "\
7495 =pod
7496
7497 =head1 NAME
7498
7499 Sys::Guestfs - Perl bindings for libguestfs
7500
7501 =head1 SYNOPSIS
7502
7503  use Sys::Guestfs;
7504
7505  my $h = Sys::Guestfs->new ();
7506  $h->add_drive ('guest.img');
7507  $h->launch ();
7508  $h->mount ('/dev/sda1', '/');
7509  $h->touch ('/hello');
7510  $h->sync ();
7511
7512 =head1 DESCRIPTION
7513
7514 The C<Sys::Guestfs> module provides a Perl XS binding to the
7515 libguestfs API for examining and modifying virtual machine
7516 disk images.
7517
7518 Amongst the things this is good for: making batch configuration
7519 changes to guests, getting disk used/free statistics (see also:
7520 virt-df), migrating between virtualization systems (see also:
7521 virt-p2v), performing partial backups, performing partial guest
7522 clones, cloning guests and changing registry/UUID/hostname info, and
7523 much else besides.
7524
7525 Libguestfs uses Linux kernel and qemu code, and can access any type of
7526 guest filesystem that Linux and qemu can, including but not limited
7527 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7528 schemes, qcow, qcow2, vmdk.
7529
7530 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7531 LVs, what filesystem is in each LV, etc.).  It can also run commands
7532 in the context of the guest.  Also you can access filesystems over FTP.
7533
7534 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7535 functions for using libguestfs from Perl, including integration
7536 with libvirt.
7537
7538 =head1 ERRORS
7539
7540 All errors turn into calls to C<croak> (see L<Carp(3)>).
7541
7542 =head1 METHODS
7543
7544 =over 4
7545
7546 =cut
7547
7548 package Sys::Guestfs;
7549
7550 use strict;
7551 use warnings;
7552
7553 require XSLoader;
7554 XSLoader::load ('Sys::Guestfs');
7555
7556 =item $h = Sys::Guestfs->new ();
7557
7558 Create a new guestfs handle.
7559
7560 =cut
7561
7562 sub new {
7563   my $proto = shift;
7564   my $class = ref ($proto) || $proto;
7565
7566   my $self = Sys::Guestfs::_create ();
7567   bless $self, $class;
7568   return $self;
7569 }
7570
7571 ";
7572
7573   (* Actions.  We only need to print documentation for these as
7574    * they are pulled in from the XS code automatically.
7575    *)
7576   List.iter (
7577     fun (name, style, _, flags, _, _, longdesc) ->
7578       if not (List.mem NotInDocs flags) then (
7579         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7580         pr "=item ";
7581         generate_perl_prototype name style;
7582         pr "\n\n";
7583         pr "%s\n\n" longdesc;
7584         if List.mem ProtocolLimitWarning flags then
7585           pr "%s\n\n" protocol_limit_warning;
7586         if List.mem DangerWillRobinson flags then
7587           pr "%s\n\n" danger_will_robinson;
7588         match deprecation_notice flags with
7589         | None -> ()
7590         | Some txt -> pr "%s\n\n" txt
7591       )
7592   ) all_functions_sorted;
7593
7594   (* End of file. *)
7595   pr "\
7596 =cut
7597
7598 1;
7599
7600 =back
7601
7602 =head1 COPYRIGHT
7603
7604 Copyright (C) 2009 Red Hat Inc.
7605
7606 =head1 LICENSE
7607
7608 Please see the file COPYING.LIB for the full license.
7609
7610 =head1 SEE ALSO
7611
7612 L<guestfs(3)>,
7613 L<guestfish(1)>,
7614 L<http://libguestfs.org>,
7615 L<Sys::Guestfs::Lib(3)>.
7616
7617 =cut
7618 "
7619
7620 and generate_perl_prototype name style =
7621   (match fst style with
7622    | RErr -> ()
7623    | RBool n
7624    | RInt n
7625    | RInt64 n
7626    | RConstString n
7627    | RConstOptString n
7628    | RString n
7629    | RBufferOut n -> pr "$%s = " n
7630    | RStruct (n,_)
7631    | RHashtable n -> pr "%%%s = " n
7632    | RStringList n
7633    | RStructList (n,_) -> pr "@%s = " n
7634   );
7635   pr "$h->%s (" name;
7636   let comma = ref false in
7637   List.iter (
7638     fun arg ->
7639       if !comma then pr ", ";
7640       comma := true;
7641       match arg with
7642       | Pathname n | Device n | Dev_or_Path n | String n
7643       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7644           pr "$%s" n
7645       | StringList n | DeviceList n ->
7646           pr "\\@%s" n
7647   ) (snd style);
7648   pr ");"
7649
7650 (* Generate Python C module. *)
7651 and generate_python_c () =
7652   generate_header CStyle LGPLv2;
7653
7654   pr "\
7655 #include <Python.h>
7656
7657 #include <stdio.h>
7658 #include <stdlib.h>
7659 #include <assert.h>
7660
7661 #include \"guestfs.h\"
7662
7663 typedef struct {
7664   PyObject_HEAD
7665   guestfs_h *g;
7666 } Pyguestfs_Object;
7667
7668 static guestfs_h *
7669 get_handle (PyObject *obj)
7670 {
7671   assert (obj);
7672   assert (obj != Py_None);
7673   return ((Pyguestfs_Object *) obj)->g;
7674 }
7675
7676 static PyObject *
7677 put_handle (guestfs_h *g)
7678 {
7679   assert (g);
7680   return
7681     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7682 }
7683
7684 /* This list should be freed (but not the strings) after use. */
7685 static char **
7686 get_string_list (PyObject *obj)
7687 {
7688   int i, len;
7689   char **r;
7690
7691   assert (obj);
7692
7693   if (!PyList_Check (obj)) {
7694     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7695     return NULL;
7696   }
7697
7698   len = PyList_Size (obj);
7699   r = malloc (sizeof (char *) * (len+1));
7700   if (r == NULL) {
7701     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7702     return NULL;
7703   }
7704
7705   for (i = 0; i < len; ++i)
7706     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7707   r[len] = NULL;
7708
7709   return r;
7710 }
7711
7712 static PyObject *
7713 put_string_list (char * const * const argv)
7714 {
7715   PyObject *list;
7716   int argc, i;
7717
7718   for (argc = 0; argv[argc] != NULL; ++argc)
7719     ;
7720
7721   list = PyList_New (argc);
7722   for (i = 0; i < argc; ++i)
7723     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7724
7725   return list;
7726 }
7727
7728 static PyObject *
7729 put_table (char * const * const argv)
7730 {
7731   PyObject *list, *item;
7732   int argc, i;
7733
7734   for (argc = 0; argv[argc] != NULL; ++argc)
7735     ;
7736
7737   list = PyList_New (argc >> 1);
7738   for (i = 0; i < argc; i += 2) {
7739     item = PyTuple_New (2);
7740     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7741     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7742     PyList_SetItem (list, i >> 1, item);
7743   }
7744
7745   return list;
7746 }
7747
7748 static void
7749 free_strings (char **argv)
7750 {
7751   int argc;
7752
7753   for (argc = 0; argv[argc] != NULL; ++argc)
7754     free (argv[argc]);
7755   free (argv);
7756 }
7757
7758 static PyObject *
7759 py_guestfs_create (PyObject *self, PyObject *args)
7760 {
7761   guestfs_h *g;
7762
7763   g = guestfs_create ();
7764   if (g == NULL) {
7765     PyErr_SetString (PyExc_RuntimeError,
7766                      \"guestfs.create: failed to allocate handle\");
7767     return NULL;
7768   }
7769   guestfs_set_error_handler (g, NULL, NULL);
7770   return put_handle (g);
7771 }
7772
7773 static PyObject *
7774 py_guestfs_close (PyObject *self, PyObject *args)
7775 {
7776   PyObject *py_g;
7777   guestfs_h *g;
7778
7779   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7780     return NULL;
7781   g = get_handle (py_g);
7782
7783   guestfs_close (g);
7784
7785   Py_INCREF (Py_None);
7786   return Py_None;
7787 }
7788
7789 ";
7790
7791   let emit_put_list_function typ =
7792     pr "static PyObject *\n";
7793     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7794     pr "{\n";
7795     pr "  PyObject *list;\n";
7796     pr "  int i;\n";
7797     pr "\n";
7798     pr "  list = PyList_New (%ss->len);\n" typ;
7799     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7800     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7801     pr "  return list;\n";
7802     pr "};\n";
7803     pr "\n"
7804   in
7805
7806   (* Structures, turned into Python dictionaries. *)
7807   List.iter (
7808     fun (typ, cols) ->
7809       pr "static PyObject *\n";
7810       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7811       pr "{\n";
7812       pr "  PyObject *dict;\n";
7813       pr "\n";
7814       pr "  dict = PyDict_New ();\n";
7815       List.iter (
7816         function
7817         | name, FString ->
7818             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7819             pr "                        PyString_FromString (%s->%s));\n"
7820               typ name
7821         | name, FBuffer ->
7822             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7823             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7824               typ name typ name
7825         | name, FUUID ->
7826             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7827             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7828               typ name
7829         | name, (FBytes|FUInt64) ->
7830             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7831             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7832               typ name
7833         | name, FInt64 ->
7834             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7835             pr "                        PyLong_FromLongLong (%s->%s));\n"
7836               typ name
7837         | name, FUInt32 ->
7838             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7839             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7840               typ name
7841         | name, FInt32 ->
7842             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7843             pr "                        PyLong_FromLong (%s->%s));\n"
7844               typ name
7845         | name, FOptPercent ->
7846             pr "  if (%s->%s >= 0)\n" typ name;
7847             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7848             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7849               typ name;
7850             pr "  else {\n";
7851             pr "    Py_INCREF (Py_None);\n";
7852             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7853             pr "  }\n"
7854         | name, FChar ->
7855             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7856             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7857       ) cols;
7858       pr "  return dict;\n";
7859       pr "};\n";
7860       pr "\n";
7861
7862   ) structs;
7863
7864   (* Emit a put_TYPE_list function definition only if that function is used. *)
7865   List.iter (
7866     function
7867     | typ, (RStructListOnly | RStructAndList) ->
7868         (* generate the function for typ *)
7869         emit_put_list_function typ
7870     | typ, _ -> () (* empty *)
7871   ) rstructs_used;
7872
7873   (* Python wrapper functions. *)
7874   List.iter (
7875     fun (name, style, _, _, _, _, _) ->
7876       pr "static PyObject *\n";
7877       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7878       pr "{\n";
7879
7880       pr "  PyObject *py_g;\n";
7881       pr "  guestfs_h *g;\n";
7882       pr "  PyObject *py_r;\n";
7883
7884       let error_code =
7885         match fst style with
7886         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7887         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7888         | RConstString _ | RConstOptString _ ->
7889             pr "  const char *r;\n"; "NULL"
7890         | RString _ -> pr "  char *r;\n"; "NULL"
7891         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7892         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7893         | RStructList (_, typ) ->
7894             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7895         | RBufferOut _ ->
7896             pr "  char *r;\n";
7897             pr "  size_t size;\n";
7898             "NULL" in
7899
7900       List.iter (
7901         function
7902         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7903             pr "  const char *%s;\n" n
7904         | OptString n -> pr "  const char *%s;\n" n
7905         | StringList n | DeviceList n ->
7906             pr "  PyObject *py_%s;\n" n;
7907             pr "  char **%s;\n" n
7908         | Bool n -> pr "  int %s;\n" n
7909         | Int n -> pr "  int %s;\n" n
7910       ) (snd style);
7911
7912       pr "\n";
7913
7914       (* Convert the parameters. *)
7915       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7916       List.iter (
7917         function
7918         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7919         | OptString _ -> pr "z"
7920         | StringList _ | DeviceList _ -> pr "O"
7921         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7922         | Int _ -> pr "i"
7923       ) (snd style);
7924       pr ":guestfs_%s\",\n" name;
7925       pr "                         &py_g";
7926       List.iter (
7927         function
7928         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7929         | OptString n -> pr ", &%s" n
7930         | StringList n | DeviceList n -> pr ", &py_%s" n
7931         | Bool n -> pr ", &%s" n
7932         | Int n -> pr ", &%s" n
7933       ) (snd style);
7934
7935       pr "))\n";
7936       pr "    return NULL;\n";
7937
7938       pr "  g = get_handle (py_g);\n";
7939       List.iter (
7940         function
7941         | Pathname _ | Device _ | Dev_or_Path _ | String _
7942         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7943         | StringList n | DeviceList n ->
7944             pr "  %s = get_string_list (py_%s);\n" n n;
7945             pr "  if (!%s) return NULL;\n" n
7946       ) (snd style);
7947
7948       pr "\n";
7949
7950       pr "  r = guestfs_%s " name;
7951       generate_c_call_args ~handle:"g" style;
7952       pr ";\n";
7953
7954       List.iter (
7955         function
7956         | Pathname _ | Device _ | Dev_or_Path _ | String _
7957         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7958         | StringList n | DeviceList n ->
7959             pr "  free (%s);\n" n
7960       ) (snd style);
7961
7962       pr "  if (r == %s) {\n" error_code;
7963       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7964       pr "    return NULL;\n";
7965       pr "  }\n";
7966       pr "\n";
7967
7968       (match fst style with
7969        | RErr ->
7970            pr "  Py_INCREF (Py_None);\n";
7971            pr "  py_r = Py_None;\n"
7972        | RInt _
7973        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7974        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7975        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7976        | RConstOptString _ ->
7977            pr "  if (r)\n";
7978            pr "    py_r = PyString_FromString (r);\n";
7979            pr "  else {\n";
7980            pr "    Py_INCREF (Py_None);\n";
7981            pr "    py_r = Py_None;\n";
7982            pr "  }\n"
7983        | RString _ ->
7984            pr "  py_r = PyString_FromString (r);\n";
7985            pr "  free (r);\n"
7986        | RStringList _ ->
7987            pr "  py_r = put_string_list (r);\n";
7988            pr "  free_strings (r);\n"
7989        | RStruct (_, typ) ->
7990            pr "  py_r = put_%s (r);\n" typ;
7991            pr "  guestfs_free_%s (r);\n" typ
7992        | RStructList (_, typ) ->
7993            pr "  py_r = put_%s_list (r);\n" typ;
7994            pr "  guestfs_free_%s_list (r);\n" typ
7995        | RHashtable n ->
7996            pr "  py_r = put_table (r);\n";
7997            pr "  free_strings (r);\n"
7998        | RBufferOut _ ->
7999            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8000            pr "  free (r);\n"
8001       );
8002
8003       pr "  return py_r;\n";
8004       pr "}\n";
8005       pr "\n"
8006   ) all_functions;
8007
8008   (* Table of functions. *)
8009   pr "static PyMethodDef methods[] = {\n";
8010   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8011   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8012   List.iter (
8013     fun (name, _, _, _, _, _, _) ->
8014       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8015         name name
8016   ) all_functions;
8017   pr "  { NULL, NULL, 0, NULL }\n";
8018   pr "};\n";
8019   pr "\n";
8020
8021   (* Init function. *)
8022   pr "\
8023 void
8024 initlibguestfsmod (void)
8025 {
8026   static int initialized = 0;
8027
8028   if (initialized) return;
8029   Py_InitModule ((char *) \"libguestfsmod\", methods);
8030   initialized = 1;
8031 }
8032 "
8033
8034 (* Generate Python module. *)
8035 and generate_python_py () =
8036   generate_header HashStyle LGPLv2;
8037
8038   pr "\
8039 u\"\"\"Python bindings for libguestfs
8040
8041 import guestfs
8042 g = guestfs.GuestFS ()
8043 g.add_drive (\"guest.img\")
8044 g.launch ()
8045 parts = g.list_partitions ()
8046
8047 The guestfs module provides a Python binding to the libguestfs API
8048 for examining and modifying virtual machine disk images.
8049
8050 Amongst the things this is good for: making batch configuration
8051 changes to guests, getting disk used/free statistics (see also:
8052 virt-df), migrating between virtualization systems (see also:
8053 virt-p2v), performing partial backups, performing partial guest
8054 clones, cloning guests and changing registry/UUID/hostname info, and
8055 much else besides.
8056
8057 Libguestfs uses Linux kernel and qemu code, and can access any type of
8058 guest filesystem that Linux and qemu can, including but not limited
8059 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8060 schemes, qcow, qcow2, vmdk.
8061
8062 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8063 LVs, what filesystem is in each LV, etc.).  It can also run commands
8064 in the context of the guest.  Also you can access filesystems over FTP.
8065
8066 Errors which happen while using the API are turned into Python
8067 RuntimeError exceptions.
8068
8069 To create a guestfs handle you usually have to perform the following
8070 sequence of calls:
8071
8072 # Create the handle, call add_drive at least once, and possibly
8073 # several times if the guest has multiple block devices:
8074 g = guestfs.GuestFS ()
8075 g.add_drive (\"guest.img\")
8076
8077 # Launch the qemu subprocess and wait for it to become ready:
8078 g.launch ()
8079
8080 # Now you can issue commands, for example:
8081 logvols = g.lvs ()
8082
8083 \"\"\"
8084
8085 import libguestfsmod
8086
8087 class GuestFS:
8088     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8089
8090     def __init__ (self):
8091         \"\"\"Create a new libguestfs handle.\"\"\"
8092         self._o = libguestfsmod.create ()
8093
8094     def __del__ (self):
8095         libguestfsmod.close (self._o)
8096
8097 ";
8098
8099   List.iter (
8100     fun (name, style, _, flags, _, _, longdesc) ->
8101       pr "    def %s " name;
8102       generate_py_call_args ~handle:"self" (snd style);
8103       pr ":\n";
8104
8105       if not (List.mem NotInDocs flags) then (
8106         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8107         let doc =
8108           match fst style with
8109           | RErr | RInt _ | RInt64 _ | RBool _
8110           | RConstOptString _ | RConstString _
8111           | RString _ | RBufferOut _ -> doc
8112           | RStringList _ ->
8113               doc ^ "\n\nThis function returns a list of strings."
8114           | RStruct (_, typ) ->
8115               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8116           | RStructList (_, typ) ->
8117               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8118           | RHashtable _ ->
8119               doc ^ "\n\nThis function returns a dictionary." in
8120         let doc =
8121           if List.mem ProtocolLimitWarning flags then
8122             doc ^ "\n\n" ^ protocol_limit_warning
8123           else doc in
8124         let doc =
8125           if List.mem DangerWillRobinson flags then
8126             doc ^ "\n\n" ^ danger_will_robinson
8127           else doc in
8128         let doc =
8129           match deprecation_notice flags with
8130           | None -> doc
8131           | Some txt -> doc ^ "\n\n" ^ txt in
8132         let doc = pod2text ~width:60 name doc in
8133         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8134         let doc = String.concat "\n        " doc in
8135         pr "        u\"\"\"%s\"\"\"\n" doc;
8136       );
8137       pr "        return libguestfsmod.%s " name;
8138       generate_py_call_args ~handle:"self._o" (snd style);
8139       pr "\n";
8140       pr "\n";
8141   ) all_functions
8142
8143 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8144 and generate_py_call_args ~handle args =
8145   pr "(%s" handle;
8146   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8147   pr ")"
8148
8149 (* Useful if you need the longdesc POD text as plain text.  Returns a
8150  * list of lines.
8151  *
8152  * Because this is very slow (the slowest part of autogeneration),
8153  * we memoize the results.
8154  *)
8155 and pod2text ~width name longdesc =
8156   let key = width, name, longdesc in
8157   try Hashtbl.find pod2text_memo key
8158   with Not_found ->
8159     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8160     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8161     close_out chan;
8162     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8163     let chan = Unix.open_process_in cmd in
8164     let lines = ref [] in
8165     let rec loop i =
8166       let line = input_line chan in
8167       if i = 1 then             (* discard the first line of output *)
8168         loop (i+1)
8169       else (
8170         let line = triml line in
8171         lines := line :: !lines;
8172         loop (i+1)
8173       ) in
8174     let lines = try loop 1 with End_of_file -> List.rev !lines in
8175     Unix.unlink filename;
8176     (match Unix.close_process_in chan with
8177      | Unix.WEXITED 0 -> ()
8178      | Unix.WEXITED i ->
8179          failwithf "pod2text: process exited with non-zero status (%d)" i
8180      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8181          failwithf "pod2text: process signalled or stopped by signal %d" i
8182     );
8183     Hashtbl.add pod2text_memo key lines;
8184     pod2text_memo_updated ();
8185     lines
8186
8187 (* Generate ruby bindings. *)
8188 and generate_ruby_c () =
8189   generate_header CStyle LGPLv2;
8190
8191   pr "\
8192 #include <stdio.h>
8193 #include <stdlib.h>
8194
8195 #include <ruby.h>
8196
8197 #include \"guestfs.h\"
8198
8199 #include \"extconf.h\"
8200
8201 /* For Ruby < 1.9 */
8202 #ifndef RARRAY_LEN
8203 #define RARRAY_LEN(r) (RARRAY((r))->len)
8204 #endif
8205
8206 static VALUE m_guestfs;                 /* guestfs module */
8207 static VALUE c_guestfs;                 /* guestfs_h handle */
8208 static VALUE e_Error;                   /* used for all errors */
8209
8210 static void ruby_guestfs_free (void *p)
8211 {
8212   if (!p) return;
8213   guestfs_close ((guestfs_h *) p);
8214 }
8215
8216 static VALUE ruby_guestfs_create (VALUE m)
8217 {
8218   guestfs_h *g;
8219
8220   g = guestfs_create ();
8221   if (!g)
8222     rb_raise (e_Error, \"failed to create guestfs handle\");
8223
8224   /* Don't print error messages to stderr by default. */
8225   guestfs_set_error_handler (g, NULL, NULL);
8226
8227   /* Wrap it, and make sure the close function is called when the
8228    * handle goes away.
8229    */
8230   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8231 }
8232
8233 static VALUE ruby_guestfs_close (VALUE gv)
8234 {
8235   guestfs_h *g;
8236   Data_Get_Struct (gv, guestfs_h, g);
8237
8238   ruby_guestfs_free (g);
8239   DATA_PTR (gv) = NULL;
8240
8241   return Qnil;
8242 }
8243
8244 ";
8245
8246   List.iter (
8247     fun (name, style, _, _, _, _, _) ->
8248       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8249       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8250       pr ")\n";
8251       pr "{\n";
8252       pr "  guestfs_h *g;\n";
8253       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8254       pr "  if (!g)\n";
8255       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8256         name;
8257       pr "\n";
8258
8259       List.iter (
8260         function
8261         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8262             pr "  Check_Type (%sv, T_STRING);\n" n;
8263             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8264             pr "  if (!%s)\n" n;
8265             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8266             pr "              \"%s\", \"%s\");\n" n name
8267         | OptString n ->
8268             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8269         | StringList n | DeviceList n ->
8270             pr "  char **%s;\n" n;
8271             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8272             pr "  {\n";
8273             pr "    int i, len;\n";
8274             pr "    len = RARRAY_LEN (%sv);\n" n;
8275             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8276               n;
8277             pr "    for (i = 0; i < len; ++i) {\n";
8278             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8279             pr "      %s[i] = StringValueCStr (v);\n" n;
8280             pr "    }\n";
8281             pr "    %s[len] = NULL;\n" n;
8282             pr "  }\n";
8283         | Bool n ->
8284             pr "  int %s = RTEST (%sv);\n" n n
8285         | Int n ->
8286             pr "  int %s = NUM2INT (%sv);\n" n n
8287       ) (snd style);
8288       pr "\n";
8289
8290       let error_code =
8291         match fst style with
8292         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8293         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8294         | RConstString _ | RConstOptString _ ->
8295             pr "  const char *r;\n"; "NULL"
8296         | RString _ -> pr "  char *r;\n"; "NULL"
8297         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8298         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8299         | RStructList (_, typ) ->
8300             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8301         | RBufferOut _ ->
8302             pr "  char *r;\n";
8303             pr "  size_t size;\n";
8304             "NULL" in
8305       pr "\n";
8306
8307       pr "  r = guestfs_%s " name;
8308       generate_c_call_args ~handle:"g" style;
8309       pr ";\n";
8310
8311       List.iter (
8312         function
8313         | Pathname _ | Device _ | Dev_or_Path _ | String _
8314         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8315         | StringList n | DeviceList n ->
8316             pr "  free (%s);\n" n
8317       ) (snd style);
8318
8319       pr "  if (r == %s)\n" error_code;
8320       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8321       pr "\n";
8322
8323       (match fst style with
8324        | RErr ->
8325            pr "  return Qnil;\n"
8326        | RInt _ | RBool _ ->
8327            pr "  return INT2NUM (r);\n"
8328        | RInt64 _ ->
8329            pr "  return ULL2NUM (r);\n"
8330        | RConstString _ ->
8331            pr "  return rb_str_new2 (r);\n";
8332        | RConstOptString _ ->
8333            pr "  if (r)\n";
8334            pr "    return rb_str_new2 (r);\n";
8335            pr "  else\n";
8336            pr "    return Qnil;\n";
8337        | RString _ ->
8338            pr "  VALUE rv = rb_str_new2 (r);\n";
8339            pr "  free (r);\n";
8340            pr "  return rv;\n";
8341        | RStringList _ ->
8342            pr "  int i, len = 0;\n";
8343            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8344            pr "  VALUE rv = rb_ary_new2 (len);\n";
8345            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8346            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8347            pr "    free (r[i]);\n";
8348            pr "  }\n";
8349            pr "  free (r);\n";
8350            pr "  return rv;\n"
8351        | RStruct (_, typ) ->
8352            let cols = cols_of_struct typ in
8353            generate_ruby_struct_code typ cols
8354        | RStructList (_, typ) ->
8355            let cols = cols_of_struct typ in
8356            generate_ruby_struct_list_code typ cols
8357        | RHashtable _ ->
8358            pr "  VALUE rv = rb_hash_new ();\n";
8359            pr "  int i;\n";
8360            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8361            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8362            pr "    free (r[i]);\n";
8363            pr "    free (r[i+1]);\n";
8364            pr "  }\n";
8365            pr "  free (r);\n";
8366            pr "  return rv;\n"
8367        | RBufferOut _ ->
8368            pr "  VALUE rv = rb_str_new (r, size);\n";
8369            pr "  free (r);\n";
8370            pr "  return rv;\n";
8371       );
8372
8373       pr "}\n";
8374       pr "\n"
8375   ) all_functions;
8376
8377   pr "\
8378 /* Initialize the module. */
8379 void Init__guestfs ()
8380 {
8381   m_guestfs = rb_define_module (\"Guestfs\");
8382   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8383   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8384
8385   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8386   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8387
8388 ";
8389   (* Define the rest of the methods. *)
8390   List.iter (
8391     fun (name, style, _, _, _, _, _) ->
8392       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8393       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8394   ) all_functions;
8395
8396   pr "}\n"
8397
8398 (* Ruby code to return a struct. *)
8399 and generate_ruby_struct_code typ cols =
8400   pr "  VALUE rv = rb_hash_new ();\n";
8401   List.iter (
8402     function
8403     | name, FString ->
8404         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8405     | name, FBuffer ->
8406         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8407     | name, FUUID ->
8408         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8409     | name, (FBytes|FUInt64) ->
8410         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8411     | name, FInt64 ->
8412         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8413     | name, FUInt32 ->
8414         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8415     | name, FInt32 ->
8416         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8417     | name, FOptPercent ->
8418         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8419     | name, FChar -> (* XXX wrong? *)
8420         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8421   ) cols;
8422   pr "  guestfs_free_%s (r);\n" typ;
8423   pr "  return rv;\n"
8424
8425 (* Ruby code to return a struct list. *)
8426 and generate_ruby_struct_list_code typ cols =
8427   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8428   pr "  int i;\n";
8429   pr "  for (i = 0; i < r->len; ++i) {\n";
8430   pr "    VALUE hv = rb_hash_new ();\n";
8431   List.iter (
8432     function
8433     | name, FString ->
8434         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8435     | name, FBuffer ->
8436         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
8437     | name, FUUID ->
8438         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8439     | name, (FBytes|FUInt64) ->
8440         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8441     | name, FInt64 ->
8442         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8443     | name, FUInt32 ->
8444         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8445     | name, FInt32 ->
8446         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8447     | name, FOptPercent ->
8448         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8449     | name, FChar -> (* XXX wrong? *)
8450         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8451   ) cols;
8452   pr "    rb_ary_push (rv, hv);\n";
8453   pr "  }\n";
8454   pr "  guestfs_free_%s_list (r);\n" typ;
8455   pr "  return rv;\n"
8456
8457 (* Generate Java bindings GuestFS.java file. *)
8458 and generate_java_java () =
8459   generate_header CStyle LGPLv2;
8460
8461   pr "\
8462 package com.redhat.et.libguestfs;
8463
8464 import java.util.HashMap;
8465 import com.redhat.et.libguestfs.LibGuestFSException;
8466 import com.redhat.et.libguestfs.PV;
8467 import com.redhat.et.libguestfs.VG;
8468 import com.redhat.et.libguestfs.LV;
8469 import com.redhat.et.libguestfs.Stat;
8470 import com.redhat.et.libguestfs.StatVFS;
8471 import com.redhat.et.libguestfs.IntBool;
8472 import com.redhat.et.libguestfs.Dirent;
8473
8474 /**
8475  * The GuestFS object is a libguestfs handle.
8476  *
8477  * @author rjones
8478  */
8479 public class GuestFS {
8480   // Load the native code.
8481   static {
8482     System.loadLibrary (\"guestfs_jni\");
8483   }
8484
8485   /**
8486    * The native guestfs_h pointer.
8487    */
8488   long g;
8489
8490   /**
8491    * Create a libguestfs handle.
8492    *
8493    * @throws LibGuestFSException
8494    */
8495   public GuestFS () throws LibGuestFSException
8496   {
8497     g = _create ();
8498   }
8499   private native long _create () throws LibGuestFSException;
8500
8501   /**
8502    * Close a libguestfs handle.
8503    *
8504    * You can also leave handles to be collected by the garbage
8505    * collector, but this method ensures that the resources used
8506    * by the handle are freed up immediately.  If you call any
8507    * other methods after closing the handle, you will get an
8508    * exception.
8509    *
8510    * @throws LibGuestFSException
8511    */
8512   public void close () throws LibGuestFSException
8513   {
8514     if (g != 0)
8515       _close (g);
8516     g = 0;
8517   }
8518   private native void _close (long g) throws LibGuestFSException;
8519
8520   public void finalize () throws LibGuestFSException
8521   {
8522     close ();
8523   }
8524
8525 ";
8526
8527   List.iter (
8528     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8529       if not (List.mem NotInDocs flags); then (
8530         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8531         let doc =
8532           if List.mem ProtocolLimitWarning flags then
8533             doc ^ "\n\n" ^ protocol_limit_warning
8534           else doc in
8535         let doc =
8536           if List.mem DangerWillRobinson flags then
8537             doc ^ "\n\n" ^ danger_will_robinson
8538           else doc in
8539         let doc =
8540           match deprecation_notice flags with
8541           | None -> doc
8542           | Some txt -> doc ^ "\n\n" ^ txt in
8543         let doc = pod2text ~width:60 name doc in
8544         let doc = List.map (            (* RHBZ#501883 *)
8545           function
8546           | "" -> "<p>"
8547           | nonempty -> nonempty
8548         ) doc in
8549         let doc = String.concat "\n   * " doc in
8550
8551         pr "  /**\n";
8552         pr "   * %s\n" shortdesc;
8553         pr "   * <p>\n";
8554         pr "   * %s\n" doc;
8555         pr "   * @throws LibGuestFSException\n";
8556         pr "   */\n";
8557         pr "  ";
8558       );
8559       generate_java_prototype ~public:true ~semicolon:false name style;
8560       pr "\n";
8561       pr "  {\n";
8562       pr "    if (g == 0)\n";
8563       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8564         name;
8565       pr "    ";
8566       if fst style <> RErr then pr "return ";
8567       pr "_%s " name;
8568       generate_java_call_args ~handle:"g" (snd style);
8569       pr ";\n";
8570       pr "  }\n";
8571       pr "  ";
8572       generate_java_prototype ~privat:true ~native:true name style;
8573       pr "\n";
8574       pr "\n";
8575   ) all_functions;
8576
8577   pr "}\n"
8578
8579 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8580 and generate_java_call_args ~handle args =
8581   pr "(%s" handle;
8582   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8583   pr ")"
8584
8585 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8586     ?(semicolon=true) name style =
8587   if privat then pr "private ";
8588   if public then pr "public ";
8589   if native then pr "native ";
8590
8591   (* return type *)
8592   (match fst style with
8593    | RErr -> pr "void ";
8594    | RInt _ -> pr "int ";
8595    | RInt64 _ -> pr "long ";
8596    | RBool _ -> pr "boolean ";
8597    | RConstString _ | RConstOptString _ | RString _
8598    | RBufferOut _ -> pr "String ";
8599    | RStringList _ -> pr "String[] ";
8600    | RStruct (_, typ) ->
8601        let name = java_name_of_struct typ in
8602        pr "%s " name;
8603    | RStructList (_, typ) ->
8604        let name = java_name_of_struct typ in
8605        pr "%s[] " name;
8606    | RHashtable _ -> pr "HashMap<String,String> ";
8607   );
8608
8609   if native then pr "_%s " name else pr "%s " name;
8610   pr "(";
8611   let needs_comma = ref false in
8612   if native then (
8613     pr "long g";
8614     needs_comma := true
8615   );
8616
8617   (* args *)
8618   List.iter (
8619     fun arg ->
8620       if !needs_comma then pr ", ";
8621       needs_comma := true;
8622
8623       match arg with
8624       | Pathname n
8625       | Device n | Dev_or_Path n
8626       | String n
8627       | OptString n
8628       | FileIn n
8629       | FileOut n ->
8630           pr "String %s" n
8631       | StringList n | DeviceList n ->
8632           pr "String[] %s" n
8633       | Bool n ->
8634           pr "boolean %s" n
8635       | Int n ->
8636           pr "int %s" n
8637   ) (snd style);
8638
8639   pr ")\n";
8640   pr "    throws LibGuestFSException";
8641   if semicolon then pr ";"
8642
8643 and generate_java_struct jtyp cols =
8644   generate_header CStyle LGPLv2;
8645
8646   pr "\
8647 package com.redhat.et.libguestfs;
8648
8649 /**
8650  * Libguestfs %s structure.
8651  *
8652  * @author rjones
8653  * @see GuestFS
8654  */
8655 public class %s {
8656 " jtyp jtyp;
8657
8658   List.iter (
8659     function
8660     | name, FString
8661     | name, FUUID
8662     | name, FBuffer -> pr "  public String %s;\n" name
8663     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8664     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8665     | name, FChar -> pr "  public char %s;\n" name
8666     | name, FOptPercent ->
8667         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8668         pr "  public float %s;\n" name
8669   ) cols;
8670
8671   pr "}\n"
8672
8673 and generate_java_c () =
8674   generate_header CStyle LGPLv2;
8675
8676   pr "\
8677 #include <stdio.h>
8678 #include <stdlib.h>
8679 #include <string.h>
8680
8681 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8682 #include \"guestfs.h\"
8683
8684 /* Note that this function returns.  The exception is not thrown
8685  * until after the wrapper function returns.
8686  */
8687 static void
8688 throw_exception (JNIEnv *env, const char *msg)
8689 {
8690   jclass cl;
8691   cl = (*env)->FindClass (env,
8692                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8693   (*env)->ThrowNew (env, cl, msg);
8694 }
8695
8696 JNIEXPORT jlong JNICALL
8697 Java_com_redhat_et_libguestfs_GuestFS__1create
8698   (JNIEnv *env, jobject obj)
8699 {
8700   guestfs_h *g;
8701
8702   g = guestfs_create ();
8703   if (g == NULL) {
8704     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8705     return 0;
8706   }
8707   guestfs_set_error_handler (g, NULL, NULL);
8708   return (jlong) (long) g;
8709 }
8710
8711 JNIEXPORT void JNICALL
8712 Java_com_redhat_et_libguestfs_GuestFS__1close
8713   (JNIEnv *env, jobject obj, jlong jg)
8714 {
8715   guestfs_h *g = (guestfs_h *) (long) jg;
8716   guestfs_close (g);
8717 }
8718
8719 ";
8720
8721   List.iter (
8722     fun (name, style, _, _, _, _, _) ->
8723       pr "JNIEXPORT ";
8724       (match fst style with
8725        | RErr -> pr "void ";
8726        | RInt _ -> pr "jint ";
8727        | RInt64 _ -> pr "jlong ";
8728        | RBool _ -> pr "jboolean ";
8729        | RConstString _ | RConstOptString _ | RString _
8730        | RBufferOut _ -> pr "jstring ";
8731        | RStruct _ | RHashtable _ ->
8732            pr "jobject ";
8733        | RStringList _ | RStructList _ ->
8734            pr "jobjectArray ";
8735       );
8736       pr "JNICALL\n";
8737       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8738       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8739       pr "\n";
8740       pr "  (JNIEnv *env, jobject obj, jlong jg";
8741       List.iter (
8742         function
8743         | Pathname n
8744         | Device n | Dev_or_Path n
8745         | String n
8746         | OptString n
8747         | FileIn n
8748         | FileOut n ->
8749             pr ", jstring j%s" n
8750         | StringList n | DeviceList n ->
8751             pr ", jobjectArray j%s" n
8752         | Bool n ->
8753             pr ", jboolean j%s" n
8754         | Int n ->
8755             pr ", jint j%s" n
8756       ) (snd style);
8757       pr ")\n";
8758       pr "{\n";
8759       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8760       let error_code, no_ret =
8761         match fst style with
8762         | RErr -> pr "  int r;\n"; "-1", ""
8763         | RBool _
8764         | RInt _ -> pr "  int r;\n"; "-1", "0"
8765         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8766         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8767         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8768         | RString _ ->
8769             pr "  jstring jr;\n";
8770             pr "  char *r;\n"; "NULL", "NULL"
8771         | RStringList _ ->
8772             pr "  jobjectArray jr;\n";
8773             pr "  int r_len;\n";
8774             pr "  jclass cl;\n";
8775             pr "  jstring jstr;\n";
8776             pr "  char **r;\n"; "NULL", "NULL"
8777         | RStruct (_, typ) ->
8778             pr "  jobject jr;\n";
8779             pr "  jclass cl;\n";
8780             pr "  jfieldID fl;\n";
8781             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8782         | RStructList (_, typ) ->
8783             pr "  jobjectArray jr;\n";
8784             pr "  jclass cl;\n";
8785             pr "  jfieldID fl;\n";
8786             pr "  jobject jfl;\n";
8787             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8788         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8789         | RBufferOut _ ->
8790             pr "  jstring jr;\n";
8791             pr "  char *r;\n";
8792             pr "  size_t size;\n";
8793             "NULL", "NULL" in
8794       List.iter (
8795         function
8796         | Pathname n
8797         | Device n | Dev_or_Path n
8798         | String n
8799         | OptString n
8800         | FileIn n
8801         | FileOut n ->
8802             pr "  const char *%s;\n" n
8803         | StringList n | DeviceList n ->
8804             pr "  int %s_len;\n" n;
8805             pr "  const char **%s;\n" n
8806         | Bool n
8807         | Int n ->
8808             pr "  int %s;\n" n
8809       ) (snd style);
8810
8811       let needs_i =
8812         (match fst style with
8813          | RStringList _ | RStructList _ -> true
8814          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8815          | RConstOptString _
8816          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8817           List.exists (function
8818                        | StringList _ -> true
8819                        | DeviceList _ -> true
8820                        | _ -> false) (snd style) in
8821       if needs_i then
8822         pr "  int i;\n";
8823
8824       pr "\n";
8825
8826       (* Get the parameters. *)
8827       List.iter (
8828         function
8829         | Pathname n
8830         | Device n | Dev_or_Path n
8831         | String n
8832         | FileIn n
8833         | FileOut n ->
8834             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8835         | OptString n ->
8836             (* This is completely undocumented, but Java null becomes
8837              * a NULL parameter.
8838              *)
8839             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8840         | StringList n | DeviceList n ->
8841             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8842             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8843             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8844             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8845               n;
8846             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8847             pr "  }\n";
8848             pr "  %s[%s_len] = NULL;\n" n n;
8849         | Bool n
8850         | Int n ->
8851             pr "  %s = j%s;\n" n n
8852       ) (snd style);
8853
8854       (* Make the call. *)
8855       pr "  r = guestfs_%s " name;
8856       generate_c_call_args ~handle:"g" style;
8857       pr ";\n";
8858
8859       (* Release the parameters. *)
8860       List.iter (
8861         function
8862         | Pathname n
8863         | Device n | Dev_or_Path n
8864         | String n
8865         | FileIn n
8866         | FileOut n ->
8867             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8868         | OptString n ->
8869             pr "  if (j%s)\n" n;
8870             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8871         | StringList n | DeviceList n ->
8872             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8873             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8874               n;
8875             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8876             pr "  }\n";
8877             pr "  free (%s);\n" n
8878         | Bool n
8879         | Int n -> ()
8880       ) (snd style);
8881
8882       (* Check for errors. *)
8883       pr "  if (r == %s) {\n" error_code;
8884       pr "    throw_exception (env, guestfs_last_error (g));\n";
8885       pr "    return %s;\n" no_ret;
8886       pr "  }\n";
8887
8888       (* Return value. *)
8889       (match fst style with
8890        | RErr -> ()
8891        | RInt _ -> pr "  return (jint) r;\n"
8892        | RBool _ -> pr "  return (jboolean) r;\n"
8893        | RInt64 _ -> pr "  return (jlong) r;\n"
8894        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8895        | RConstOptString _ ->
8896            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8897        | RString _ ->
8898            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8899            pr "  free (r);\n";
8900            pr "  return jr;\n"
8901        | RStringList _ ->
8902            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8903            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8904            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8905            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8906            pr "  for (i = 0; i < r_len; ++i) {\n";
8907            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8908            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8909            pr "    free (r[i]);\n";
8910            pr "  }\n";
8911            pr "  free (r);\n";
8912            pr "  return jr;\n"
8913        | RStruct (_, typ) ->
8914            let jtyp = java_name_of_struct typ in
8915            let cols = cols_of_struct typ in
8916            generate_java_struct_return typ jtyp cols
8917        | RStructList (_, typ) ->
8918            let jtyp = java_name_of_struct typ in
8919            let cols = cols_of_struct typ in
8920            generate_java_struct_list_return typ jtyp cols
8921        | RHashtable _ ->
8922            (* XXX *)
8923            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8924            pr "  return NULL;\n"
8925        | RBufferOut _ ->
8926            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8927            pr "  free (r);\n";
8928            pr "  return jr;\n"
8929       );
8930
8931       pr "}\n";
8932       pr "\n"
8933   ) all_functions
8934
8935 and generate_java_struct_return typ jtyp cols =
8936   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8937   pr "  jr = (*env)->AllocObject (env, cl);\n";
8938   List.iter (
8939     function
8940     | name, FString ->
8941         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8942         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8943     | name, FUUID ->
8944         pr "  {\n";
8945         pr "    char s[33];\n";
8946         pr "    memcpy (s, r->%s, 32);\n" name;
8947         pr "    s[32] = 0;\n";
8948         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8949         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8950         pr "  }\n";
8951     | name, FBuffer ->
8952         pr "  {\n";
8953         pr "    int len = r->%s_len;\n" name;
8954         pr "    char s[len+1];\n";
8955         pr "    memcpy (s, r->%s, len);\n" name;
8956         pr "    s[len] = 0;\n";
8957         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8958         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8959         pr "  }\n";
8960     | name, (FBytes|FUInt64|FInt64) ->
8961         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8962         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8963     | name, (FUInt32|FInt32) ->
8964         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8965         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8966     | name, FOptPercent ->
8967         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8968         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8969     | name, FChar ->
8970         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8971         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8972   ) cols;
8973   pr "  free (r);\n";
8974   pr "  return jr;\n"
8975
8976 and generate_java_struct_list_return typ jtyp cols =
8977   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8978   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8979   pr "  for (i = 0; i < r->len; ++i) {\n";
8980   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8981   List.iter (
8982     function
8983     | name, FString ->
8984         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8985         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8986     | name, FUUID ->
8987         pr "    {\n";
8988         pr "      char s[33];\n";
8989         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8990         pr "      s[32] = 0;\n";
8991         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8992         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8993         pr "    }\n";
8994     | name, FBuffer ->
8995         pr "    {\n";
8996         pr "      int len = r->val[i].%s_len;\n" name;
8997         pr "      char s[len+1];\n";
8998         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8999         pr "      s[len] = 0;\n";
9000         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9001         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9002         pr "    }\n";
9003     | name, (FBytes|FUInt64|FInt64) ->
9004         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9005         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9006     | name, (FUInt32|FInt32) ->
9007         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9008         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9009     | name, FOptPercent ->
9010         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9011         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9012     | name, FChar ->
9013         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9014         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9015   ) cols;
9016   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9017   pr "  }\n";
9018   pr "  guestfs_free_%s_list (r);\n" typ;
9019   pr "  return jr;\n"
9020
9021 and generate_java_makefile_inc () =
9022   generate_header HashStyle GPLv2;
9023
9024   pr "java_built_sources = \\\n";
9025   List.iter (
9026     fun (typ, jtyp) ->
9027         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9028   ) java_structs;
9029   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9030
9031 and generate_haskell_hs () =
9032   generate_header HaskellStyle LGPLv2;
9033
9034   (* XXX We only know how to generate partial FFI for Haskell
9035    * at the moment.  Please help out!
9036    *)
9037   let can_generate style =
9038     match style with
9039     | RErr, _
9040     | RInt _, _
9041     | RInt64 _, _ -> true
9042     | RBool _, _
9043     | RConstString _, _
9044     | RConstOptString _, _
9045     | RString _, _
9046     | RStringList _, _
9047     | RStruct _, _
9048     | RStructList _, _
9049     | RHashtable _, _
9050     | RBufferOut _, _ -> false in
9051
9052   pr "\
9053 {-# INCLUDE <guestfs.h> #-}
9054 {-# LANGUAGE ForeignFunctionInterface #-}
9055
9056 module Guestfs (
9057   create";
9058
9059   (* List out the names of the actions we want to export. *)
9060   List.iter (
9061     fun (name, style, _, _, _, _, _) ->
9062       if can_generate style then pr ",\n  %s" name
9063   ) all_functions;
9064
9065   pr "
9066   ) where
9067 import Foreign
9068 import Foreign.C
9069 import Foreign.C.Types
9070 import IO
9071 import Control.Exception
9072 import Data.Typeable
9073
9074 data GuestfsS = GuestfsS            -- represents the opaque C struct
9075 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9076 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9077
9078 -- XXX define properly later XXX
9079 data PV = PV
9080 data VG = VG
9081 data LV = LV
9082 data IntBool = IntBool
9083 data Stat = Stat
9084 data StatVFS = StatVFS
9085 data Hashtable = Hashtable
9086
9087 foreign import ccall unsafe \"guestfs_create\" c_create
9088   :: IO GuestfsP
9089 foreign import ccall unsafe \"&guestfs_close\" c_close
9090   :: FunPtr (GuestfsP -> IO ())
9091 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9092   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9093
9094 create :: IO GuestfsH
9095 create = do
9096   p <- c_create
9097   c_set_error_handler p nullPtr nullPtr
9098   h <- newForeignPtr c_close p
9099   return h
9100
9101 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9102   :: GuestfsP -> IO CString
9103
9104 -- last_error :: GuestfsH -> IO (Maybe String)
9105 -- last_error h = do
9106 --   str <- withForeignPtr h (\\p -> c_last_error p)
9107 --   maybePeek peekCString str
9108
9109 last_error :: GuestfsH -> IO (String)
9110 last_error h = do
9111   str <- withForeignPtr h (\\p -> c_last_error p)
9112   if (str == nullPtr)
9113     then return \"no error\"
9114     else peekCString str
9115
9116 ";
9117
9118   (* Generate wrappers for each foreign function. *)
9119   List.iter (
9120     fun (name, style, _, _, _, _, _) ->
9121       if can_generate style then (
9122         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9123         pr "  :: ";
9124         generate_haskell_prototype ~handle:"GuestfsP" style;
9125         pr "\n";
9126         pr "\n";
9127         pr "%s :: " name;
9128         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9129         pr "\n";
9130         pr "%s %s = do\n" name
9131           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9132         pr "  r <- ";
9133         (* Convert pointer arguments using with* functions. *)
9134         List.iter (
9135           function
9136           | FileIn n
9137           | FileOut n
9138           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9139           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9140           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9141           | Bool _ | Int _ -> ()
9142         ) (snd style);
9143         (* Convert integer arguments. *)
9144         let args =
9145           List.map (
9146             function
9147             | Bool n -> sprintf "(fromBool %s)" n
9148             | Int n -> sprintf "(fromIntegral %s)" n
9149             | FileIn n | FileOut n
9150             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9151           ) (snd style) in
9152         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9153           (String.concat " " ("p" :: args));
9154         (match fst style with
9155          | RErr | RInt _ | RInt64 _ | RBool _ ->
9156              pr "  if (r == -1)\n";
9157              pr "    then do\n";
9158              pr "      err <- last_error h\n";
9159              pr "      fail err\n";
9160          | RConstString _ | RConstOptString _ | RString _
9161          | RStringList _ | RStruct _
9162          | RStructList _ | RHashtable _ | RBufferOut _ ->
9163              pr "  if (r == nullPtr)\n";
9164              pr "    then do\n";
9165              pr "      err <- last_error h\n";
9166              pr "      fail err\n";
9167         );
9168         (match fst style with
9169          | RErr ->
9170              pr "    else return ()\n"
9171          | RInt _ ->
9172              pr "    else return (fromIntegral r)\n"
9173          | RInt64 _ ->
9174              pr "    else return (fromIntegral r)\n"
9175          | RBool _ ->
9176              pr "    else return (toBool r)\n"
9177          | RConstString _
9178          | RConstOptString _
9179          | RString _
9180          | RStringList _
9181          | RStruct _
9182          | RStructList _
9183          | RHashtable _
9184          | RBufferOut _ ->
9185              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9186         );
9187         pr "\n";
9188       )
9189   ) all_functions
9190
9191 and generate_haskell_prototype ~handle ?(hs = false) style =
9192   pr "%s -> " handle;
9193   let string = if hs then "String" else "CString" in
9194   let int = if hs then "Int" else "CInt" in
9195   let bool = if hs then "Bool" else "CInt" in
9196   let int64 = if hs then "Integer" else "Int64" in
9197   List.iter (
9198     fun arg ->
9199       (match arg with
9200        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9201        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9202        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9203        | Bool _ -> pr "%s" bool
9204        | Int _ -> pr "%s" int
9205        | FileIn _ -> pr "%s" string
9206        | FileOut _ -> pr "%s" string
9207       );
9208       pr " -> ";
9209   ) (snd style);
9210   pr "IO (";
9211   (match fst style with
9212    | RErr -> if not hs then pr "CInt"
9213    | RInt _ -> pr "%s" int
9214    | RInt64 _ -> pr "%s" int64
9215    | RBool _ -> pr "%s" bool
9216    | RConstString _ -> pr "%s" string
9217    | RConstOptString _ -> pr "Maybe %s" string
9218    | RString _ -> pr "%s" string
9219    | RStringList _ -> pr "[%s]" string
9220    | RStruct (_, typ) ->
9221        let name = java_name_of_struct typ in
9222        pr "%s" name
9223    | RStructList (_, typ) ->
9224        let name = java_name_of_struct typ in
9225        pr "[%s]" name
9226    | RHashtable _ -> pr "Hashtable"
9227    | RBufferOut _ -> pr "%s" string
9228   );
9229   pr ")"
9230
9231 and generate_bindtests () =
9232   generate_header CStyle LGPLv2;
9233
9234   pr "\
9235 #include <stdio.h>
9236 #include <stdlib.h>
9237 #include <inttypes.h>
9238 #include <string.h>
9239
9240 #include \"guestfs.h\"
9241 #include \"guestfs-internal-actions.h\"
9242 #include \"guestfs_protocol.h\"
9243
9244 #define error guestfs_error
9245 #define safe_calloc guestfs_safe_calloc
9246 #define safe_malloc guestfs_safe_malloc
9247
9248 static void
9249 print_strings (char *const *argv)
9250 {
9251   int argc;
9252
9253   printf (\"[\");
9254   for (argc = 0; argv[argc] != NULL; ++argc) {
9255     if (argc > 0) printf (\", \");
9256     printf (\"\\\"%%s\\\"\", argv[argc]);
9257   }
9258   printf (\"]\\n\");
9259 }
9260
9261 /* The test0 function prints its parameters to stdout. */
9262 ";
9263
9264   let test0, tests =
9265     match test_functions with
9266     | [] -> assert false
9267     | test0 :: tests -> test0, tests in
9268
9269   let () =
9270     let (name, style, _, _, _, _, _) = test0 in
9271     generate_prototype ~extern:false ~semicolon:false ~newline:true
9272       ~handle:"g" ~prefix:"guestfs__" name style;
9273     pr "{\n";
9274     List.iter (
9275       function
9276       | Pathname n
9277       | Device n | Dev_or_Path n
9278       | String n
9279       | FileIn n
9280       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9281       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9282       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9283       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9284       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9285     ) (snd style);
9286     pr "  /* Java changes stdout line buffering so we need this: */\n";
9287     pr "  fflush (stdout);\n";
9288     pr "  return 0;\n";
9289     pr "}\n";
9290     pr "\n" in
9291
9292   List.iter (
9293     fun (name, style, _, _, _, _, _) ->
9294       if String.sub name (String.length name - 3) 3 <> "err" then (
9295         pr "/* Test normal return. */\n";
9296         generate_prototype ~extern:false ~semicolon:false ~newline:true
9297           ~handle:"g" ~prefix:"guestfs__" name style;
9298         pr "{\n";
9299         (match fst style with
9300          | RErr ->
9301              pr "  return 0;\n"
9302          | RInt _ ->
9303              pr "  int r;\n";
9304              pr "  sscanf (val, \"%%d\", &r);\n";
9305              pr "  return r;\n"
9306          | RInt64 _ ->
9307              pr "  int64_t r;\n";
9308              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9309              pr "  return r;\n"
9310          | RBool _ ->
9311              pr "  return strcmp (val, \"true\") == 0;\n"
9312          | RConstString _
9313          | RConstOptString _ ->
9314              (* Can't return the input string here.  Return a static
9315               * string so we ensure we get a segfault if the caller
9316               * tries to free it.
9317               *)
9318              pr "  return \"static string\";\n"
9319          | RString _ ->
9320              pr "  return strdup (val);\n"
9321          | RStringList _ ->
9322              pr "  char **strs;\n";
9323              pr "  int n, i;\n";
9324              pr "  sscanf (val, \"%%d\", &n);\n";
9325              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9326              pr "  for (i = 0; i < n; ++i) {\n";
9327              pr "    strs[i] = safe_malloc (g, 16);\n";
9328              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9329              pr "  }\n";
9330              pr "  strs[n] = NULL;\n";
9331              pr "  return strs;\n"
9332          | RStruct (_, typ) ->
9333              pr "  struct guestfs_%s *r;\n" typ;
9334              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9335              pr "  return r;\n"
9336          | RStructList (_, typ) ->
9337              pr "  struct guestfs_%s_list *r;\n" typ;
9338              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9339              pr "  sscanf (val, \"%%d\", &r->len);\n";
9340              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9341              pr "  return r;\n"
9342          | RHashtable _ ->
9343              pr "  char **strs;\n";
9344              pr "  int n, i;\n";
9345              pr "  sscanf (val, \"%%d\", &n);\n";
9346              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9347              pr "  for (i = 0; i < n; ++i) {\n";
9348              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9349              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9350              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9351              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9352              pr "  }\n";
9353              pr "  strs[n*2] = NULL;\n";
9354              pr "  return strs;\n"
9355          | RBufferOut _ ->
9356              pr "  return strdup (val);\n"
9357         );
9358         pr "}\n";
9359         pr "\n"
9360       ) else (
9361         pr "/* Test error return. */\n";
9362         generate_prototype ~extern:false ~semicolon:false ~newline:true
9363           ~handle:"g" ~prefix:"guestfs__" name style;
9364         pr "{\n";
9365         pr "  error (g, \"error\");\n";
9366         (match fst style with
9367          | RErr | RInt _ | RInt64 _ | RBool _ ->
9368              pr "  return -1;\n"
9369          | RConstString _ | RConstOptString _
9370          | RString _ | RStringList _ | RStruct _
9371          | RStructList _
9372          | RHashtable _
9373          | RBufferOut _ ->
9374              pr "  return NULL;\n"
9375         );
9376         pr "}\n";
9377         pr "\n"
9378       )
9379   ) tests
9380
9381 and generate_ocaml_bindtests () =
9382   generate_header OCamlStyle GPLv2;
9383
9384   pr "\
9385 let () =
9386   let g = Guestfs.create () in
9387 ";
9388
9389   let mkargs args =
9390     String.concat " " (
9391       List.map (
9392         function
9393         | CallString s -> "\"" ^ s ^ "\""
9394         | CallOptString None -> "None"
9395         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9396         | CallStringList xs ->
9397             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9398         | CallInt i when i >= 0 -> string_of_int i
9399         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9400         | CallBool b -> string_of_bool b
9401       ) args
9402     )
9403   in
9404
9405   generate_lang_bindtests (
9406     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9407   );
9408
9409   pr "print_endline \"EOF\"\n"
9410
9411 and generate_perl_bindtests () =
9412   pr "#!/usr/bin/perl -w\n";
9413   generate_header HashStyle GPLv2;
9414
9415   pr "\
9416 use strict;
9417
9418 use Sys::Guestfs;
9419
9420 my $g = Sys::Guestfs->new ();
9421 ";
9422
9423   let mkargs args =
9424     String.concat ", " (
9425       List.map (
9426         function
9427         | CallString s -> "\"" ^ s ^ "\""
9428         | CallOptString None -> "undef"
9429         | CallOptString (Some s) -> sprintf "\"%s\"" s
9430         | CallStringList xs ->
9431             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9432         | CallInt i -> string_of_int i
9433         | CallBool b -> if b then "1" else "0"
9434       ) args
9435     )
9436   in
9437
9438   generate_lang_bindtests (
9439     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9440   );
9441
9442   pr "print \"EOF\\n\"\n"
9443
9444 and generate_python_bindtests () =
9445   generate_header HashStyle GPLv2;
9446
9447   pr "\
9448 import guestfs
9449
9450 g = guestfs.GuestFS ()
9451 ";
9452
9453   let mkargs args =
9454     String.concat ", " (
9455       List.map (
9456         function
9457         | CallString s -> "\"" ^ s ^ "\""
9458         | CallOptString None -> "None"
9459         | CallOptString (Some s) -> sprintf "\"%s\"" s
9460         | CallStringList xs ->
9461             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9462         | CallInt i -> string_of_int i
9463         | CallBool b -> if b then "1" else "0"
9464       ) args
9465     )
9466   in
9467
9468   generate_lang_bindtests (
9469     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9470   );
9471
9472   pr "print \"EOF\"\n"
9473
9474 and generate_ruby_bindtests () =
9475   generate_header HashStyle GPLv2;
9476
9477   pr "\
9478 require 'guestfs'
9479
9480 g = Guestfs::create()
9481 ";
9482
9483   let mkargs args =
9484     String.concat ", " (
9485       List.map (
9486         function
9487         | CallString s -> "\"" ^ s ^ "\""
9488         | CallOptString None -> "nil"
9489         | CallOptString (Some s) -> sprintf "\"%s\"" s
9490         | CallStringList xs ->
9491             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9492         | CallInt i -> string_of_int i
9493         | CallBool b -> string_of_bool b
9494       ) args
9495     )
9496   in
9497
9498   generate_lang_bindtests (
9499     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
9500   );
9501
9502   pr "print \"EOF\\n\"\n"
9503
9504 and generate_java_bindtests () =
9505   generate_header CStyle GPLv2;
9506
9507   pr "\
9508 import com.redhat.et.libguestfs.*;
9509
9510 public class Bindtests {
9511     public static void main (String[] argv)
9512     {
9513         try {
9514             GuestFS g = new GuestFS ();
9515 ";
9516
9517   let mkargs args =
9518     String.concat ", " (
9519       List.map (
9520         function
9521         | CallString s -> "\"" ^ s ^ "\""
9522         | CallOptString None -> "null"
9523         | CallOptString (Some s) -> sprintf "\"%s\"" s
9524         | CallStringList xs ->
9525             "new String[]{" ^
9526               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9527         | CallInt i -> string_of_int i
9528         | CallBool b -> string_of_bool b
9529       ) args
9530     )
9531   in
9532
9533   generate_lang_bindtests (
9534     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9535   );
9536
9537   pr "
9538             System.out.println (\"EOF\");
9539         }
9540         catch (Exception exn) {
9541             System.err.println (exn);
9542             System.exit (1);
9543         }
9544     }
9545 }
9546 "
9547
9548 and generate_haskell_bindtests () =
9549   generate_header HaskellStyle GPLv2;
9550
9551   pr "\
9552 module Bindtests where
9553 import qualified Guestfs
9554
9555 main = do
9556   g <- Guestfs.create
9557 ";
9558
9559   let mkargs args =
9560     String.concat " " (
9561       List.map (
9562         function
9563         | CallString s -> "\"" ^ s ^ "\""
9564         | CallOptString None -> "Nothing"
9565         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9566         | CallStringList xs ->
9567             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9568         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9569         | CallInt i -> string_of_int i
9570         | CallBool true -> "True"
9571         | CallBool false -> "False"
9572       ) args
9573     )
9574   in
9575
9576   generate_lang_bindtests (
9577     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9578   );
9579
9580   pr "  putStrLn \"EOF\"\n"
9581
9582 (* Language-independent bindings tests - we do it this way to
9583  * ensure there is parity in testing bindings across all languages.
9584  *)
9585 and generate_lang_bindtests call =
9586   call "test0" [CallString "abc"; CallOptString (Some "def");
9587                 CallStringList []; CallBool false;
9588                 CallInt 0; CallString "123"; CallString "456"];
9589   call "test0" [CallString "abc"; CallOptString None;
9590                 CallStringList []; CallBool false;
9591                 CallInt 0; CallString "123"; CallString "456"];
9592   call "test0" [CallString ""; CallOptString (Some "def");
9593                 CallStringList []; CallBool false;
9594                 CallInt 0; CallString "123"; CallString "456"];
9595   call "test0" [CallString ""; CallOptString (Some "");
9596                 CallStringList []; CallBool false;
9597                 CallInt 0; CallString "123"; CallString "456"];
9598   call "test0" [CallString "abc"; CallOptString (Some "def");
9599                 CallStringList ["1"]; CallBool false;
9600                 CallInt 0; CallString "123"; CallString "456"];
9601   call "test0" [CallString "abc"; CallOptString (Some "def");
9602                 CallStringList ["1"; "2"]; CallBool false;
9603                 CallInt 0; CallString "123"; CallString "456"];
9604   call "test0" [CallString "abc"; CallOptString (Some "def");
9605                 CallStringList ["1"]; CallBool true;
9606                 CallInt 0; CallString "123"; CallString "456"];
9607   call "test0" [CallString "abc"; CallOptString (Some "def");
9608                 CallStringList ["1"]; CallBool false;
9609                 CallInt (-1); CallString "123"; CallString "456"];
9610   call "test0" [CallString "abc"; CallOptString (Some "def");
9611                 CallStringList ["1"]; CallBool false;
9612                 CallInt (-2); CallString "123"; CallString "456"];
9613   call "test0" [CallString "abc"; CallOptString (Some "def");
9614                 CallStringList ["1"]; CallBool false;
9615                 CallInt 1; CallString "123"; CallString "456"];
9616   call "test0" [CallString "abc"; CallOptString (Some "def");
9617                 CallStringList ["1"]; CallBool false;
9618                 CallInt 2; CallString "123"; CallString "456"];
9619   call "test0" [CallString "abc"; CallOptString (Some "def");
9620                 CallStringList ["1"]; CallBool false;
9621                 CallInt 4095; CallString "123"; CallString "456"];
9622   call "test0" [CallString "abc"; CallOptString (Some "def");
9623                 CallStringList ["1"]; CallBool false;
9624                 CallInt 0; CallString ""; CallString ""]
9625
9626 (* XXX Add here tests of the return and error functions. *)
9627
9628 (* This is used to generate the src/MAX_PROC_NR file which
9629  * contains the maximum procedure number, a surrogate for the
9630  * ABI version number.  See src/Makefile.am for the details.
9631  *)
9632 and generate_max_proc_nr () =
9633   let proc_nrs = List.map (
9634     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9635   ) daemon_functions in
9636
9637   let max_proc_nr = List.fold_left max 0 proc_nrs in
9638
9639   pr "%d\n" max_proc_nr
9640
9641 let output_to filename =
9642   let filename_new = filename ^ ".new" in
9643   chan := open_out filename_new;
9644   let close () =
9645     close_out !chan;
9646     chan := stdout;
9647
9648     (* Is the new file different from the current file? *)
9649     if Sys.file_exists filename && files_equal filename filename_new then
9650       Unix.unlink filename_new          (* same, so skip it *)
9651     else (
9652       (* different, overwrite old one *)
9653       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9654       Unix.rename filename_new filename;
9655       Unix.chmod filename 0o444;
9656       printf "written %s\n%!" filename;
9657     )
9658   in
9659   close
9660
9661 (* Main program. *)
9662 let () =
9663   check_functions ();
9664
9665   if not (Sys.file_exists "HACKING") then (
9666     eprintf "\
9667 You are probably running this from the wrong directory.
9668 Run it from the top source directory using the command
9669   src/generator.ml
9670 ";
9671     exit 1
9672   );
9673
9674   let close = output_to "src/guestfs_protocol.x" in
9675   generate_xdr ();
9676   close ();
9677
9678   let close = output_to "src/guestfs-structs.h" in
9679   generate_structs_h ();
9680   close ();
9681
9682   let close = output_to "src/guestfs-actions.h" in
9683   generate_actions_h ();
9684   close ();
9685
9686   let close = output_to "src/guestfs-internal-actions.h" in
9687   generate_internal_actions_h ();
9688   close ();
9689
9690   let close = output_to "src/guestfs-actions.c" in
9691   generate_client_actions ();
9692   close ();
9693
9694   let close = output_to "daemon/actions.h" in
9695   generate_daemon_actions_h ();
9696   close ();
9697
9698   let close = output_to "daemon/stubs.c" in
9699   generate_daemon_actions ();
9700   close ();
9701
9702   let close = output_to "daemon/names.c" in
9703   generate_daemon_names ();
9704   close ();
9705
9706   let close = output_to "capitests/tests.c" in
9707   generate_tests ();
9708   close ();
9709
9710   let close = output_to "src/guestfs-bindtests.c" in
9711   generate_bindtests ();
9712   close ();
9713
9714   let close = output_to "fish/cmds.c" in
9715   generate_fish_cmds ();
9716   close ();
9717
9718   let close = output_to "fish/completion.c" in
9719   generate_fish_completion ();
9720   close ();
9721
9722   let close = output_to "guestfs-structs.pod" in
9723   generate_structs_pod ();
9724   close ();
9725
9726   let close = output_to "guestfs-actions.pod" in
9727   generate_actions_pod ();
9728   close ();
9729
9730   let close = output_to "guestfish-actions.pod" in
9731   generate_fish_actions_pod ();
9732   close ();
9733
9734   let close = output_to "ocaml/guestfs.mli" in
9735   generate_ocaml_mli ();
9736   close ();
9737
9738   let close = output_to "ocaml/guestfs.ml" in
9739   generate_ocaml_ml ();
9740   close ();
9741
9742   let close = output_to "ocaml/guestfs_c_actions.c" in
9743   generate_ocaml_c ();
9744   close ();
9745
9746   let close = output_to "ocaml/bindtests.ml" in
9747   generate_ocaml_bindtests ();
9748   close ();
9749
9750   let close = output_to "perl/Guestfs.xs" in
9751   generate_perl_xs ();
9752   close ();
9753
9754   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9755   generate_perl_pm ();
9756   close ();
9757
9758   let close = output_to "perl/bindtests.pl" in
9759   generate_perl_bindtests ();
9760   close ();
9761
9762   let close = output_to "python/guestfs-py.c" in
9763   generate_python_c ();
9764   close ();
9765
9766   let close = output_to "python/guestfs.py" in
9767   generate_python_py ();
9768   close ();
9769
9770   let close = output_to "python/bindtests.py" in
9771   generate_python_bindtests ();
9772   close ();
9773
9774   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9775   generate_ruby_c ();
9776   close ();
9777
9778   let close = output_to "ruby/bindtests.rb" in
9779   generate_ruby_bindtests ();
9780   close ();
9781
9782   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9783   generate_java_java ();
9784   close ();
9785
9786   List.iter (
9787     fun (typ, jtyp) ->
9788       let cols = cols_of_struct typ in
9789       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9790       let close = output_to filename in
9791       generate_java_struct jtyp cols;
9792       close ();
9793   ) java_structs;
9794
9795   let close = output_to "java/Makefile.inc" in
9796   generate_java_makefile_inc ();
9797   close ();
9798
9799   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9800   generate_java_c ();
9801   close ();
9802
9803   let close = output_to "java/Bindtests.java" in
9804   generate_java_bindtests ();
9805   close ();
9806
9807   let close = output_to "haskell/Guestfs.hs" in
9808   generate_haskell_hs ();
9809   close ();
9810
9811   let close = output_to "haskell/Bindtests.hs" in
9812   generate_haskell_bindtests ();
9813   close ();
9814
9815   let close = output_to "src/MAX_PROC_NR" in
9816   generate_max_proc_nr ();
9817   close ();
9818
9819   (* Always generate this file last, and unconditionally.  It's used
9820    * by the Makefile to know when we must re-run the generator.
9821    *)
9822   let chan = open_out "src/stamp-generator" in
9823   fprintf chan "1\n";
9824   close_out chan