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