New API: find0 (unlimited version of find)
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table below), and
25  * daemon/<somefile>.c to write the implementation.
26  *
27  * After editing this file, run it (./src/generator.ml) to regenerate all the
28  * output files.  Note that if you are using a separate build directory you
29  * must run generator.ml from the _source_ directory.
30  *
31  * IMPORTANT: This script should NOT print any warnings.  If it prints
32  * warnings, you should treat them as errors.
33  *)
34
35 #load "unix.cma";;
36 #load "str.cma";;
37
38 open Printf
39
40 type style = ret * args
41 and ret =
42     (* "RErr" as a return value means an int used as a simple error
43      * indication, ie. 0 or -1.
44      *)
45   | RErr
46
47     (* "RInt" as a return value means an int which is -1 for error
48      * or any value >= 0 on success.  Only use this for smallish
49      * positive ints (0 <= i < 2^30).
50      *)
51   | RInt of string
52
53     (* "RInt64" is the same as RInt, but is guaranteed to be able
54      * to return a full 64 bit value, _except_ that -1 means error
55      * (so -1 cannot be a valid, non-error return value).
56      *)
57   | RInt64 of string
58
59     (* "RBool" is a bool return value which can be true/false or
60      * -1 for error.
61      *)
62   | RBool of string
63
64     (* "RConstString" is a string that refers to a constant value.
65      * The return value must NOT be NULL (since NULL indicates
66      * an error).
67      *
68      * Try to avoid using this.  In particular you cannot use this
69      * for values returned from the daemon, because there is no
70      * thread-safe way to return them in the C API.
71      *)
72   | RConstString of string
73
74     (* "RConstOptString" is an even more broken version of
75      * "RConstString".  The returned string may be NULL and there
76      * is no way to return an error indication.  Avoid using this!
77      *)
78   | RConstOptString of string
79
80     (* "RString" is a returned string.  It must NOT be NULL, since
81      * a NULL return indicates an error.  The caller frees this.
82      *)
83   | RString of string
84
85     (* "RStringList" is a list of strings.  No string in the list
86      * can be NULL.  The caller frees the strings and the array.
87      *)
88   | RStringList of string
89
90     (* "RStruct" is a function which returns a single named structure
91      * or an error indication (in C, a struct, and in other languages
92      * with varying representations, but usually very efficient).  See
93      * after the function list below for the structures.
94      *)
95   | RStruct of string * string          (* name of retval, name of struct *)
96
97     (* "RStructList" is a function which returns either a list/array
98      * of structures (could be zero-length), or an error indication.
99      *)
100   | RStructList of string * string      (* name of retval, name of struct *)
101
102     (* Key-value pairs of untyped strings.  Turns into a hashtable or
103      * dictionary in languages which support it.  DON'T use this as a
104      * general "bucket" for results.  Prefer a stronger typed return
105      * value if one is available, or write a custom struct.  Don't use
106      * this if the list could potentially be very long, since it is
107      * inefficient.  Keys should be unique.  NULLs are not permitted.
108      *)
109   | RHashtable of string
110
111     (* "RBufferOut" is handled almost exactly like RString, but
112      * it allows the string to contain arbitrary 8 bit data including
113      * ASCII NUL.  In the C API this causes an implicit extra parameter
114      * to be added of type <size_t *size_r>.  The extra parameter
115      * returns the actual size of the return buffer in bytes.
116      *
117      * Other programming languages support strings with arbitrary 8 bit
118      * data.
119      *
120      * At the RPC layer we have to use the opaque<> type instead of
121      * string<>.  Returned data is still limited to the max message
122      * size (ie. ~ 2 MB).
123      *)
124   | RBufferOut of string
125
126 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
127
128     (* Note in future we should allow a "variable args" parameter as
129      * the final parameter, to allow commands like
130      *   chmod mode file [file(s)...]
131      * This is not implemented yet, but many commands (such as chmod)
132      * are currently defined with the argument order keeping this future
133      * possibility in mind.
134      *)
135 and argt =
136   | String of string    (* const char *name, cannot be NULL *)
137   | Device of string    (* /dev device name, cannot be NULL *)
138   | Pathname of string  (* file name, cannot be NULL *)
139   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
140   | OptString of string (* const char *name, may be NULL *)
141   | StringList of string(* list of strings (each string cannot be NULL) *)
142   | DeviceList of string(* list of Device names (each cannot be NULL) *)
143   | Bool of string      (* boolean *)
144   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
145     (* These are treated as filenames (simple string parameters) in
146      * the C API and bindings.  But in the RPC protocol, we transfer
147      * the actual file content up to or down from the daemon.
148      * FileIn: local machine -> daemon (in request)
149      * FileOut: daemon -> local machine (in reply)
150      * In guestfish (only), the special name "-" means read from
151      * stdin or write to stdout.
152      *)
153   | FileIn of string
154   | FileOut of string
155 (* Not implemented:
156     (* Opaque buffer which can contain arbitrary 8 bit data.
157      * In the C API, this is expressed as <char *, int> pair.
158      * Most other languages have a string type which can contain
159      * ASCII NUL.  We use whatever type is appropriate for each
160      * language.
161      * Buffers are limited by the total message size.  To transfer
162      * large blocks of data, use FileIn/FileOut parameters instead.
163      * To return an arbitrary buffer, use RBufferOut.
164      *)
165   | BufferIn of string
166 *)
167
168 type flags =
169   | ProtocolLimitWarning  (* display warning about protocol size limits *)
170   | DangerWillRobinson    (* flags particularly dangerous commands *)
171   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
172   | FishAction of string  (* call this function in guestfish *)
173   | NotInFish             (* do not export via guestfish *)
174   | NotInDocs             (* do not add this function to documentation *)
175   | DeprecatedBy of string (* function is deprecated, use .. instead *)
176
177 (* You can supply zero or as many tests as you want per API call.
178  *
179  * Note that the test environment has 3 block devices, of size 500MB,
180  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
181  * a fourth ISO block device with some known files on it (/dev/sdd).
182  *
183  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
184  * Number of cylinders was 63 for IDE emulated disks with precisely
185  * the same size.  How exactly this is calculated is a mystery.
186  *
187  * The ISO block device (/dev/sdd) comes from images/test.iso.
188  *
189  * To be able to run the tests in a reasonable amount of time,
190  * the virtual machine and block devices are reused between tests.
191  * So don't try testing kill_subprocess :-x
192  *
193  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
194  *
195  * Don't assume anything about the previous contents of the block
196  * devices.  Use 'Init*' to create some initial scenarios.
197  *
198  * You can add a prerequisite clause to any individual test.  This
199  * is a run-time check, which, if it fails, causes the test to be
200  * skipped.  Useful if testing a command which might not work on
201  * all variations of libguestfs builds.  A test that has prerequisite
202  * of 'Always' is run unconditionally.
203  *
204  * In addition, packagers can skip individual tests by setting the
205  * environment variables:     eg:
206  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
207  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
208  *)
209 type tests = (test_init * test_prereq * test) list
210 and test =
211     (* Run the command sequence and just expect nothing to fail. *)
212   | TestRun of seq
213
214     (* Run the command sequence and expect the output of the final
215      * command to be the string.
216      *)
217   | TestOutput of seq * string
218
219     (* Run the command sequence and expect the output of the final
220      * command to be the list of strings.
221      *)
222   | TestOutputList of seq * string list
223
224     (* Run the command sequence and expect the output of the final
225      * command to be the list of block devices (could be either
226      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
227      * character of each string).
228      *)
229   | TestOutputListOfDevices of seq * string list
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the integer.
233      *)
234   | TestOutputInt of seq * int
235
236     (* Run the command sequence and expect the output of the final
237      * command to be <op> <int>, eg. ">=", "1".
238      *)
239   | TestOutputIntOp of seq * string * int
240
241     (* Run the command sequence and expect the output of the final
242      * command to be a true value (!= 0 or != NULL).
243      *)
244   | TestOutputTrue of seq
245
246     (* Run the command sequence and expect the output of the final
247      * command to be a false value (== 0 or == NULL, but not an error).
248      *)
249   | TestOutputFalse of seq
250
251     (* Run the command sequence and expect the output of the final
252      * command to be a list of the given length (but don't care about
253      * content).
254      *)
255   | TestOutputLength of seq * int
256
257     (* Run the command sequence and expect the output of the final
258      * command to be a buffer (RBufferOut), ie. string + size.
259      *)
260   | TestOutputBuffer of seq * string
261
262     (* Run the command sequence and expect the output of the final
263      * command to be a structure.
264      *)
265   | TestOutputStruct of seq * test_field_compare list
266
267     (* Run the command sequence and expect the final command (only)
268      * to fail.
269      *)
270   | TestLastFail of seq
271
272 and test_field_compare =
273   | CompareWithInt of string * int
274   | CompareWithIntOp of string * string * int
275   | CompareWithString of string * string
276   | CompareFieldsIntEq of string * string
277   | CompareFieldsStrEq of string * string
278
279 (* Test prerequisites. *)
280 and test_prereq =
281     (* Test always runs. *)
282   | Always
283
284     (* Test is currently disabled - eg. it fails, or it tests some
285      * unimplemented feature.
286      *)
287   | Disabled
288
289     (* 'string' is some C code (a function body) that should return
290      * true or false.  The test will run if the code returns true.
291      *)
292   | If of string
293
294     (* As for 'If' but the test runs _unless_ the code returns true. *)
295   | Unless of string
296
297 (* Some initial scenarios for testing. *)
298 and test_init =
299     (* Do nothing, block devices could contain random stuff including
300      * LVM PVs, and some filesystems might be mounted.  This is usually
301      * a bad idea.
302      *)
303   | InitNone
304
305     (* Block devices are empty and no filesystems are mounted. *)
306   | InitEmpty
307
308     (* /dev/sda contains a single partition /dev/sda1, with random
309      * content.  /dev/sdb and /dev/sdc may have random content.
310      * No LVM.
311      *)
312   | InitPartition
313
314     (* /dev/sda contains a single partition /dev/sda1, which is formatted
315      * as ext2, empty [except for lost+found] and mounted on /.
316      * /dev/sdb and /dev/sdc may have random content.
317      * No LVM.
318      *)
319   | InitBasicFS
320
321     (* /dev/sda:
322      *   /dev/sda1 (is a PV):
323      *     /dev/VG/LV (size 8MB):
324      *       formatted as ext2, empty [except for lost+found], mounted on /
325      * /dev/sdb and /dev/sdc may have random content.
326      *)
327   | InitBasicFSonLVM
328
329     (* /dev/sdd (the ISO, see images/ directory in source)
330      * is mounted on /
331      *)
332   | InitISOFS
333
334 (* Sequence of commands for testing. *)
335 and seq = cmd list
336 and cmd = string list
337
338 (* Note about long descriptions: When referring to another
339  * action, use the format C<guestfs_other> (ie. the full name of
340  * the C function).  This will be replaced as appropriate in other
341  * language bindings.
342  *
343  * Apart from that, long descriptions are just perldoc paragraphs.
344  *)
345
346 (* Generate a random UUID (used in tests). *)
347 let uuidgen () =
348   let chan = Unix.open_process_in "uuidgen" in
349   let uuid = input_line chan in
350   (match Unix.close_process_in chan with
351    | Unix.WEXITED 0 -> ()
352    | Unix.WEXITED _ ->
353        failwith "uuidgen: process exited with non-zero status"
354    | Unix.WSIGNALED _ | Unix.WSTOPPED _ ->
355        failwith "uuidgen: process signalled or stopped by signal"
356   );
357   uuid
358
359 (* These test functions are used in the language binding tests. *)
360
361 let test_all_args = [
362   String "str";
363   OptString "optstr";
364   StringList "strlist";
365   Bool "b";
366   Int "integer";
367   FileIn "filein";
368   FileOut "fileout";
369 ]
370
371 let test_all_rets = [
372   (* except for RErr, which is tested thoroughly elsewhere *)
373   "test0rint",         RInt "valout";
374   "test0rint64",       RInt64 "valout";
375   "test0rbool",        RBool "valout";
376   "test0rconststring", RConstString "valout";
377   "test0rconstoptstring", RConstOptString "valout";
378   "test0rstring",      RString "valout";
379   "test0rstringlist",  RStringList "valout";
380   "test0rstruct",      RStruct ("valout", "lvm_pv");
381   "test0rstructlist",  RStructList ("valout", "lvm_pv");
382   "test0rhashtable",   RHashtable "valout";
383 ]
384
385 let test_functions = [
386   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
387    [],
388    "internal test function - do not use",
389    "\
390 This is an internal test function which is used to test whether
391 the automatically generated bindings can handle every possible
392 parameter type correctly.
393
394 It echos the contents of each parameter to stdout.
395
396 You probably don't want to call this function.");
397 ] @ List.flatten (
398   List.map (
399     fun (name, ret) ->
400       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
401         [],
402         "internal test function - do not use",
403         "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 return type correctly.
407
408 It converts string C<val> to the return type.
409
410 You probably don't want to call this function.");
411        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
412         [],
413         "internal test function - do not use",
414         "\
415 This is an internal test function which is used to test whether
416 the automatically generated bindings can handle every possible
417 return type correctly.
418
419 This function always returns an error.
420
421 You probably don't want to call this function.")]
422   ) test_all_rets
423 )
424
425 (* non_daemon_functions are any functions which don't get processed
426  * in the daemon, eg. functions for setting and getting local
427  * configuration values.
428  *)
429
430 let non_daemon_functions = test_functions @ [
431   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
432    [],
433    "launch the qemu subprocess",
434    "\
435 Internally libguestfs is implemented by running a virtual machine
436 using L<qemu(1)>.
437
438 You should call this after configuring the handle
439 (eg. adding drives) but before performing any actions.");
440
441   ("wait_ready", (RErr, []), -1, [NotInFish],
442    [],
443    "wait until the qemu subprocess launches (no op)",
444    "\
445 This function is a no op.
446
447 In versions of the API E<lt> 1.0.71 you had to call this function
448 just after calling C<guestfs_launch> to wait for the launch
449 to complete.  However this is no longer necessary because
450 C<guestfs_launch> now does the waiting.
451
452 If you see any calls to this function in code then you can just
453 remove them, unless you want to retain compatibility with older
454 versions of the API.");
455
456   ("kill_subprocess", (RErr, []), -1, [],
457    [],
458    "kill the qemu subprocess",
459    "\
460 This kills the qemu subprocess.  You should never need to call this.");
461
462   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
463    [],
464    "add an image to examine or modify",
465    "\
466 This function adds a virtual machine disk image C<filename> to the
467 guest.  The first time you call this function, the disk appears as IDE
468 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
469 so on.
470
471 You don't necessarily need to be root when using libguestfs.  However
472 you obviously do need sufficient permissions to access the filename
473 for whatever operations you want to perform (ie. read access if you
474 just want to read the image or write access if you want to modify the
475 image).
476
477 This is equivalent to the qemu parameter
478 C<-drive file=filename,cache=off,if=...>.
479 C<cache=off> is omitted in cases where it is not supported by
480 the underlying filesystem.
481
482 Note that this call checks for the existence of C<filename>.  This
483 stops you from specifying other types of drive which are supported
484 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
485 the general C<guestfs_config> call instead.");
486
487   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
488    [],
489    "add a CD-ROM disk image to examine",
490    "\
491 This function adds a virtual CD-ROM disk image to the guest.
492
493 This is equivalent to the qemu parameter C<-cdrom filename>.
494
495 Note that this call checks for the existence of C<filename>.  This
496 stops you from specifying other types of drive which are supported
497 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
498 the general C<guestfs_config> call instead.");
499
500   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
501    [],
502    "add a drive in snapshot mode (read-only)",
503    "\
504 This adds a drive in snapshot mode, making it effectively
505 read-only.
506
507 Note that writes to the device are allowed, and will be seen for
508 the duration of the guestfs handle, but they are written
509 to a temporary file which is discarded as soon as the guestfs
510 handle is closed.  We don't currently have any method to enable
511 changes to be committed, although qemu can support this.
512
513 This is equivalent to the qemu parameter
514 C<-drive file=filename,snapshot=on,if=...>.
515
516 Note that this call checks for the existence of C<filename>.  This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
519 the general C<guestfs_config> call instead.");
520
521   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
522    [],
523    "add qemu parameters",
524    "\
525 This can be used to add arbitrary qemu command line parameters
526 of the form C<-param value>.  Actually it's not quite arbitrary - we
527 prevent you from setting some parameters which would interfere with
528 parameters that we use.
529
530 The first character of C<param> string must be a C<-> (dash).
531
532 C<value> can be NULL.");
533
534   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
535    [],
536    "set the qemu binary",
537    "\
538 Set the qemu binary that we will use.
539
540 The default is chosen when the library was compiled by the
541 configure script.
542
543 You can also override this by setting the C<LIBGUESTFS_QEMU>
544 environment variable.
545
546 Setting C<qemu> to C<NULL> restores the default qemu binary.");
547
548   ("get_qemu", (RConstString "qemu", []), -1, [],
549    [InitNone, Always, TestRun (
550       [["get_qemu"]])],
551    "get the qemu binary",
552    "\
553 Return the current qemu binary.
554
555 This is always non-NULL.  If it wasn't set already, then this will
556 return the default qemu binary name.");
557
558   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
559    [],
560    "set the search path",
561    "\
562 Set the path that libguestfs searches for kernel and initrd.img.
563
564 The default is C<$libdir/guestfs> unless overridden by setting
565 C<LIBGUESTFS_PATH> environment variable.
566
567 Setting C<path> to C<NULL> restores the default path.");
568
569   ("get_path", (RConstString "path", []), -1, [],
570    [InitNone, Always, TestRun (
571       [["get_path"]])],
572    "get the search path",
573    "\
574 Return the current search path.
575
576 This is always non-NULL.  If it wasn't set already, then this will
577 return the default path.");
578
579   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
580    [],
581    "add options to kernel command line",
582    "\
583 This function is used to add additional options to the
584 guest kernel command line.
585
586 The default is C<NULL> unless overridden by setting
587 C<LIBGUESTFS_APPEND> environment variable.
588
589 Setting C<append> to C<NULL> means I<no> additional options
590 are passed (libguestfs always adds a few of its own).");
591
592   ("get_append", (RConstOptString "append", []), -1, [],
593    (* This cannot be tested with the current framework.  The
594     * function can return NULL in normal operations, which the
595     * test framework interprets as an error.
596     *)
597    [],
598    "get the additional kernel options",
599    "\
600 Return the additional kernel options which are added to the
601 guest kernel command line.
602
603 If C<NULL> then no options are added.");
604
605   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
606    [],
607    "set autosync mode",
608    "\
609 If C<autosync> is true, this enables autosync.  Libguestfs will make a
610 best effort attempt to run C<guestfs_umount_all> followed by
611 C<guestfs_sync> when the handle is closed
612 (also if the program exits without closing handles).
613
614 This is disabled by default (except in guestfish where it is
615 enabled by default).");
616
617   ("get_autosync", (RBool "autosync", []), -1, [],
618    [InitNone, Always, TestRun (
619       [["get_autosync"]])],
620    "get autosync mode",
621    "\
622 Get the autosync flag.");
623
624   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
625    [],
626    "set verbose mode",
627    "\
628 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
629
630 Verbose messages are disabled unless the environment variable
631 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
632
633   ("get_verbose", (RBool "verbose", []), -1, [],
634    [],
635    "get verbose mode",
636    "\
637 This returns the verbose messages flag.");
638
639   ("is_ready", (RBool "ready", []), -1, [],
640    [InitNone, Always, TestOutputTrue (
641       [["is_ready"]])],
642    "is ready to accept commands",
643    "\
644 This returns true iff this handle is ready to accept commands
645 (in the C<READY> state).
646
647 For more information on states, see L<guestfs(3)>.");
648
649   ("is_config", (RBool "config", []), -1, [],
650    [InitNone, Always, TestOutputFalse (
651       [["is_config"]])],
652    "is in configuration state",
653    "\
654 This returns true iff this handle is being configured
655 (in the C<CONFIG> state).
656
657 For more information on states, see L<guestfs(3)>.");
658
659   ("is_launching", (RBool "launching", []), -1, [],
660    [InitNone, Always, TestOutputFalse (
661       [["is_launching"]])],
662    "is launching subprocess",
663    "\
664 This returns true iff this handle is launching the subprocess
665 (in the C<LAUNCHING> state).
666
667 For more information on states, see L<guestfs(3)>.");
668
669   ("is_busy", (RBool "busy", []), -1, [],
670    [InitNone, Always, TestOutputFalse (
671       [["is_busy"]])],
672    "is busy processing a command",
673    "\
674 This returns true iff this handle is busy processing a command
675 (in the C<BUSY> state).
676
677 For more information on states, see L<guestfs(3)>.");
678
679   ("get_state", (RInt "state", []), -1, [],
680    [],
681    "get the current state",
682    "\
683 This returns the current state as an opaque integer.  This is
684 only useful for printing debug and internal error messages.
685
686 For more information on states, see L<guestfs(3)>.");
687
688   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
689    [InitNone, Always, TestOutputInt (
690       [["set_memsize"; "500"];
691        ["get_memsize"]], 500)],
692    "set memory allocated to the qemu subprocess",
693    "\
694 This sets the memory size in megabytes allocated to the
695 qemu subprocess.  This only has any effect if called before
696 C<guestfs_launch>.
697
698 You can also change this by setting the environment
699 variable C<LIBGUESTFS_MEMSIZE> before the handle is
700 created.
701
702 For more information on the architecture of libguestfs,
703 see L<guestfs(3)>.");
704
705   ("get_memsize", (RInt "memsize", []), -1, [],
706    [InitNone, Always, TestOutputIntOp (
707       [["get_memsize"]], ">=", 256)],
708    "get memory allocated to the qemu subprocess",
709    "\
710 This gets the memory size in megabytes allocated to the
711 qemu subprocess.
712
713 If C<guestfs_set_memsize> was not called
714 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
715 then this returns the compiled-in default value for memsize.
716
717 For more information on the architecture of libguestfs,
718 see L<guestfs(3)>.");
719
720   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
721    [InitNone, Always, TestOutputIntOp (
722       [["get_pid"]], ">=", 1)],
723    "get PID of qemu subprocess",
724    "\
725 Return the process ID of the qemu subprocess.  If there is no
726 qemu subprocess, then this will return an error.
727
728 This is an internal call used for debugging and testing.");
729
730   ("version", (RStruct ("version", "version"), []), -1, [],
731    [InitNone, Always, TestOutputStruct (
732       [["version"]], [CompareWithInt ("major", 1)])],
733    "get the library version number",
734    "\
735 Return the libguestfs version number that the program is linked
736 against.
737
738 Note that because of dynamic linking this is not necessarily
739 the version of libguestfs that you compiled against.  You can
740 compile the program, and then at runtime dynamically link
741 against a completely different C<libguestfs.so> library.
742
743 This call was added in version C<1.0.58>.  In previous
744 versions of libguestfs there was no way to get the version
745 number.  From C code you can use ELF weak linking tricks to find out if
746 this symbol exists (if it doesn't, then it's an earlier version).
747
748 The call returns a structure with four elements.  The first
749 three (C<major>, C<minor> and C<release>) are numbers and
750 correspond to the usual version triplet.  The fourth element
751 (C<extra>) is a string and is normally empty, but may be
752 used for distro-specific information.
753
754 To construct the original version string:
755 C<$major.$minor.$release$extra>
756
757 I<Note:> Don't use this call to test for availability
758 of features.  Distro backports makes this unreliable.");
759
760   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
761    [InitNone, Always, TestOutputTrue (
762       [["set_selinux"; "true"];
763        ["get_selinux"]])],
764    "set SELinux enabled or disabled at appliance boot",
765    "\
766 This sets the selinux flag that is passed to the appliance
767 at boot time.  The default is C<selinux=0> (disabled).
768
769 Note that if SELinux is enabled, it is always in
770 Permissive mode (C<enforcing=0>).
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_selinux", (RBool "selinux", []), -1, [],
776    [],
777    "get SELinux enabled flag",
778    "\
779 This returns the current setting of the selinux flag which
780 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
781
782 For more information on the architecture of libguestfs,
783 see L<guestfs(3)>.");
784
785   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
786    [InitNone, Always, TestOutputFalse (
787       [["set_trace"; "false"];
788        ["get_trace"]])],
789    "enable or disable command traces",
790    "\
791 If the command trace flag is set to 1, then commands are
792 printed on stdout before they are executed in a format
793 which is very similar to the one used by guestfish.  In
794 other words, you can run a program with this enabled, and
795 you will get out a script which you can feed to guestfish
796 to perform the same set of actions.
797
798 If you want to trace C API calls into libguestfs (and
799 other libraries) then possibly a better way is to use
800 the external ltrace(1) command.
801
802 Command traces are disabled unless the environment variable
803 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
804
805   ("get_trace", (RBool "trace", []), -1, [],
806    [],
807    "get command trace enabled flag",
808    "\
809 Return the command trace flag.");
810
811   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
812    [InitNone, Always, TestOutputFalse (
813       [["set_direct"; "false"];
814        ["get_direct"]])],
815    "enable or disable direct appliance mode",
816    "\
817 If the direct appliance mode flag is enabled, then stdin and
818 stdout are passed directly through to the appliance once it
819 is launched.
820
821 One consequence of this is that log messages aren't caught
822 by the library and handled by C<guestfs_set_log_message_callback>,
823 but go straight to stdout.
824
825 You probably don't want to use this unless you know what you
826 are doing.
827
828 The default is disabled.");
829
830   ("get_direct", (RBool "direct", []), -1, [],
831    [],
832    "get direct appliance mode flag",
833    "\
834 Return the direct appliance mode flag.");
835
836 ]
837
838 (* daemon_functions are any functions which cause some action
839  * to take place in the daemon.
840  *)
841
842 let daemon_functions = [
843   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
844    [InitEmpty, Always, TestOutput (
845       [["sfdiskM"; "/dev/sda"; ","];
846        ["mkfs"; "ext2"; "/dev/sda1"];
847        ["mount"; "/dev/sda1"; "/"];
848        ["write_file"; "/new"; "new file contents"; "0"];
849        ["cat"; "/new"]], "new file contents")],
850    "mount a guest disk at a position in the filesystem",
851    "\
852 Mount a guest disk at a position in the filesystem.  Block devices
853 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
854 the guest.  If those block devices contain partitions, they will have
855 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
856 names can be used.
857
858 The rules are the same as for L<mount(2)>:  A filesystem must
859 first be mounted on C</> before others can be mounted.  Other
860 filesystems can only be mounted on directories which already
861 exist.
862
863 The mounted filesystem is writable, if we have sufficient permissions
864 on the underlying device.
865
866 The filesystem options C<sync> and C<noatime> are set with this
867 call, in order to improve reliability.");
868
869   ("sync", (RErr, []), 2, [],
870    [ InitEmpty, Always, TestRun [["sync"]]],
871    "sync disks, writes are flushed through to the disk image",
872    "\
873 This syncs the disk, so that any writes are flushed through to the
874 underlying disk image.
875
876 You should always call this if you have modified a disk image, before
877 closing the handle.");
878
879   ("touch", (RErr, [Pathname "path"]), 3, [],
880    [InitBasicFS, Always, TestOutputTrue (
881       [["touch"; "/new"];
882        ["exists"; "/new"]])],
883    "update file timestamps or create a new file",
884    "\
885 Touch acts like the L<touch(1)> command.  It can be used to
886 update the timestamps on a file, or, if the file does not exist,
887 to create a new zero-length file.");
888
889   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
890    [InitISOFS, Always, TestOutput (
891       [["cat"; "/known-2"]], "abcdef\n")],
892    "list the contents of a file",
893    "\
894 Return the contents of the file named C<path>.
895
896 Note that this function cannot correctly handle binary files
897 (specifically, files containing C<\\0> character which is treated
898 as end of string).  For those you need to use the C<guestfs_read_file>
899 or C<guestfs_download> functions which have a more complex interface.");
900
901   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
902    [], (* XXX Tricky to test because it depends on the exact format
903         * of the 'ls -l' command, which changes between F10 and F11.
904         *)
905    "list the files in a directory (long format)",
906    "\
907 List the files in C<directory> (relative to the root directory,
908 there is no cwd) in the format of 'ls -la'.
909
910 This command is mostly useful for interactive sessions.  It
911 is I<not> intended that you try to parse the output string.");
912
913   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
914    [InitBasicFS, Always, TestOutputList (
915       [["touch"; "/new"];
916        ["touch"; "/newer"];
917        ["touch"; "/newest"];
918        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
919    "list the files in a directory",
920    "\
921 List the files in C<directory> (relative to the root directory,
922 there is no cwd).  The '.' and '..' entries are not returned, but
923 hidden files are shown.
924
925 This command is mostly useful for interactive sessions.  Programs
926 should probably use C<guestfs_readdir> instead.");
927
928   ("list_devices", (RStringList "devices", []), 7, [],
929    [InitEmpty, Always, TestOutputListOfDevices (
930       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
931    "list the block devices",
932    "\
933 List all the block devices.
934
935 The full block device names are returned, eg. C</dev/sda>");
936
937   ("list_partitions", (RStringList "partitions", []), 8, [],
938    [InitBasicFS, Always, TestOutputListOfDevices (
939       [["list_partitions"]], ["/dev/sda1"]);
940     InitEmpty, Always, TestOutputListOfDevices (
941       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
942        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
943    "list the partitions",
944    "\
945 List all the partitions detected on all block devices.
946
947 The full partition device names are returned, eg. C</dev/sda1>
948
949 This does not return logical volumes.  For that you will need to
950 call C<guestfs_lvs>.");
951
952   ("pvs", (RStringList "physvols", []), 9, [],
953    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
954       [["pvs"]], ["/dev/sda1"]);
955     InitEmpty, Always, TestOutputListOfDevices (
956       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
957        ["pvcreate"; "/dev/sda1"];
958        ["pvcreate"; "/dev/sda2"];
959        ["pvcreate"; "/dev/sda3"];
960        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
961    "list the LVM physical volumes (PVs)",
962    "\
963 List all the physical volumes detected.  This is the equivalent
964 of the L<pvs(8)> command.
965
966 This returns a list of just the device names that contain
967 PVs (eg. C</dev/sda2>).
968
969 See also C<guestfs_pvs_full>.");
970
971   ("vgs", (RStringList "volgroups", []), 10, [],
972    [InitBasicFSonLVM, Always, TestOutputList (
973       [["vgs"]], ["VG"]);
974     InitEmpty, Always, TestOutputList (
975       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
976        ["pvcreate"; "/dev/sda1"];
977        ["pvcreate"; "/dev/sda2"];
978        ["pvcreate"; "/dev/sda3"];
979        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
980        ["vgcreate"; "VG2"; "/dev/sda3"];
981        ["vgs"]], ["VG1"; "VG2"])],
982    "list the LVM volume groups (VGs)",
983    "\
984 List all the volumes groups detected.  This is the equivalent
985 of the L<vgs(8)> command.
986
987 This returns a list of just the volume group names that were
988 detected (eg. C<VolGroup00>).
989
990 See also C<guestfs_vgs_full>.");
991
992   ("lvs", (RStringList "logvols", []), 11, [],
993    [InitBasicFSonLVM, Always, TestOutputList (
994       [["lvs"]], ["/dev/VG/LV"]);
995     InitEmpty, Always, TestOutputList (
996       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
997        ["pvcreate"; "/dev/sda1"];
998        ["pvcreate"; "/dev/sda2"];
999        ["pvcreate"; "/dev/sda3"];
1000        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1001        ["vgcreate"; "VG2"; "/dev/sda3"];
1002        ["lvcreate"; "LV1"; "VG1"; "50"];
1003        ["lvcreate"; "LV2"; "VG1"; "50"];
1004        ["lvcreate"; "LV3"; "VG2"; "50"];
1005        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1006    "list the LVM logical volumes (LVs)",
1007    "\
1008 List all the logical volumes detected.  This is the equivalent
1009 of the L<lvs(8)> command.
1010
1011 This returns a list of the logical volume device names
1012 (eg. C</dev/VolGroup00/LogVol00>).
1013
1014 See also C<guestfs_lvs_full>.");
1015
1016   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [],
1017    [], (* XXX how to test? *)
1018    "list the LVM physical volumes (PVs)",
1019    "\
1020 List all the physical volumes detected.  This is the equivalent
1021 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1022
1023   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [],
1024    [], (* XXX how to test? *)
1025    "list the LVM volume groups (VGs)",
1026    "\
1027 List all the volumes groups detected.  This is the equivalent
1028 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1029
1030   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [],
1031    [], (* XXX how to test? *)
1032    "list the LVM logical volumes (LVs)",
1033    "\
1034 List all the logical volumes detected.  This is the equivalent
1035 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1036
1037   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1038    [InitISOFS, Always, TestOutputList (
1039       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1040     InitISOFS, Always, TestOutputList (
1041       [["read_lines"; "/empty"]], [])],
1042    "read file as lines",
1043    "\
1044 Return the contents of the file named C<path>.
1045
1046 The file contents are returned as a list of lines.  Trailing
1047 C<LF> and C<CRLF> character sequences are I<not> returned.
1048
1049 Note that this function cannot correctly handle binary files
1050 (specifically, files containing C<\\0> character which is treated
1051 as end of line).  For those you need to use the C<guestfs_read_file>
1052 function which has a more complex interface.");
1053
1054   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [],
1055    [], (* XXX Augeas code needs tests. *)
1056    "create a new Augeas handle",
1057    "\
1058 Create a new Augeas handle for editing configuration files.
1059 If there was any previous Augeas handle associated with this
1060 guestfs session, then it is closed.
1061
1062 You must call this before using any other C<guestfs_aug_*>
1063 commands.
1064
1065 C<root> is the filesystem root.  C<root> must not be NULL,
1066 use C</> instead.
1067
1068 The flags are the same as the flags defined in
1069 E<lt>augeas.hE<gt>, the logical I<or> of the following
1070 integers:
1071
1072 =over 4
1073
1074 =item C<AUG_SAVE_BACKUP> = 1
1075
1076 Keep the original file with a C<.augsave> extension.
1077
1078 =item C<AUG_SAVE_NEWFILE> = 2
1079
1080 Save changes into a file with extension C<.augnew>, and
1081 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1082
1083 =item C<AUG_TYPE_CHECK> = 4
1084
1085 Typecheck lenses (can be expensive).
1086
1087 =item C<AUG_NO_STDINC> = 8
1088
1089 Do not use standard load path for modules.
1090
1091 =item C<AUG_SAVE_NOOP> = 16
1092
1093 Make save a no-op, just record what would have been changed.
1094
1095 =item C<AUG_NO_LOAD> = 32
1096
1097 Do not load the tree in C<guestfs_aug_init>.
1098
1099 =back
1100
1101 To close the handle, you can call C<guestfs_aug_close>.
1102
1103 To find out more about Augeas, see L<http://augeas.net/>.");
1104
1105   ("aug_close", (RErr, []), 26, [],
1106    [], (* XXX Augeas code needs tests. *)
1107    "close the current Augeas handle",
1108    "\
1109 Close the current Augeas handle and free up any resources
1110 used by it.  After calling this, you have to call
1111 C<guestfs_aug_init> again before you can use any other
1112 Augeas functions.");
1113
1114   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [],
1115    [], (* XXX Augeas code needs tests. *)
1116    "define an Augeas variable",
1117    "\
1118 Defines an Augeas variable C<name> whose value is the result
1119 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1120 undefined.
1121
1122 On success this returns the number of nodes in C<expr>, or
1123 C<0> if C<expr> evaluates to something which is not a nodeset.");
1124
1125   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [],
1126    [], (* XXX Augeas code needs tests. *)
1127    "define an Augeas node",
1128    "\
1129 Defines a variable C<name> whose value is the result of
1130 evaluating C<expr>.
1131
1132 If C<expr> evaluates to an empty nodeset, a node is created,
1133 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1134 C<name> will be the nodeset containing that single node.
1135
1136 On success this returns a pair containing the
1137 number of nodes in the nodeset, and a boolean flag
1138 if a node was created.");
1139
1140   ("aug_get", (RString "val", [String "augpath"]), 19, [],
1141    [], (* XXX Augeas code needs tests. *)
1142    "look up the value of an Augeas path",
1143    "\
1144 Look up the value associated with C<path>.  If C<path>
1145 matches exactly one node, the C<value> is returned.");
1146
1147   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [],
1148    [], (* XXX Augeas code needs tests. *)
1149    "set Augeas path to value",
1150    "\
1151 Set the value associated with C<path> to C<value>.");
1152
1153   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [],
1154    [], (* XXX Augeas code needs tests. *)
1155    "insert a sibling Augeas node",
1156    "\
1157 Create a new sibling C<label> for C<path>, inserting it into
1158 the tree before or after C<path> (depending on the boolean
1159 flag C<before>).
1160
1161 C<path> must match exactly one existing node in the tree, and
1162 C<label> must be a label, ie. not contain C</>, C<*> or end
1163 with a bracketed index C<[N]>.");
1164
1165   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [],
1166    [], (* XXX Augeas code needs tests. *)
1167    "remove an Augeas path",
1168    "\
1169 Remove C<path> and all of its children.
1170
1171 On success this returns the number of entries which were removed.");
1172
1173   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [],
1174    [], (* XXX Augeas code needs tests. *)
1175    "move Augeas node",
1176    "\
1177 Move the node C<src> to C<dest>.  C<src> must match exactly
1178 one node.  C<dest> is overwritten if it exists.");
1179
1180   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [],
1181    [], (* XXX Augeas code needs tests. *)
1182    "return Augeas nodes which match augpath",
1183    "\
1184 Returns a list of paths which match the path expression C<path>.
1185 The returned paths are sufficiently qualified so that they match
1186 exactly one node in the current tree.");
1187
1188   ("aug_save", (RErr, []), 25, [],
1189    [], (* XXX Augeas code needs tests. *)
1190    "write all pending Augeas changes to disk",
1191    "\
1192 This writes all pending changes to disk.
1193
1194 The flags which were passed to C<guestfs_aug_init> affect exactly
1195 how files are saved.");
1196
1197   ("aug_load", (RErr, []), 27, [],
1198    [], (* XXX Augeas code needs tests. *)
1199    "load files into the tree",
1200    "\
1201 Load files into the tree.
1202
1203 See C<aug_load> in the Augeas documentation for the full gory
1204 details.");
1205
1206   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [],
1207    [], (* XXX Augeas code needs tests. *)
1208    "list Augeas nodes under augpath",
1209    "\
1210 This is just a shortcut for listing C<guestfs_aug_match>
1211 C<path/*> and sorting the resulting nodes into alphabetical order.");
1212
1213   ("rm", (RErr, [Pathname "path"]), 29, [],
1214    [InitBasicFS, Always, TestRun
1215       [["touch"; "/new"];
1216        ["rm"; "/new"]];
1217     InitBasicFS, Always, TestLastFail
1218       [["rm"; "/new"]];
1219     InitBasicFS, Always, TestLastFail
1220       [["mkdir"; "/new"];
1221        ["rm"; "/new"]]],
1222    "remove a file",
1223    "\
1224 Remove the single file C<path>.");
1225
1226   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1227    [InitBasicFS, Always, TestRun
1228       [["mkdir"; "/new"];
1229        ["rmdir"; "/new"]];
1230     InitBasicFS, Always, TestLastFail
1231       [["rmdir"; "/new"]];
1232     InitBasicFS, Always, TestLastFail
1233       [["touch"; "/new"];
1234        ["rmdir"; "/new"]]],
1235    "remove a directory",
1236    "\
1237 Remove the single directory C<path>.");
1238
1239   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1240    [InitBasicFS, Always, TestOutputFalse
1241       [["mkdir"; "/new"];
1242        ["mkdir"; "/new/foo"];
1243        ["touch"; "/new/foo/bar"];
1244        ["rm_rf"; "/new"];
1245        ["exists"; "/new"]]],
1246    "remove a file or directory recursively",
1247    "\
1248 Remove the file or directory C<path>, recursively removing the
1249 contents if its a directory.  This is like the C<rm -rf> shell
1250 command.");
1251
1252   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1253    [InitBasicFS, Always, TestOutputTrue
1254       [["mkdir"; "/new"];
1255        ["is_dir"; "/new"]];
1256     InitBasicFS, Always, TestLastFail
1257       [["mkdir"; "/new/foo/bar"]]],
1258    "create a directory",
1259    "\
1260 Create a directory named C<path>.");
1261
1262   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1263    [InitBasicFS, Always, TestOutputTrue
1264       [["mkdir_p"; "/new/foo/bar"];
1265        ["is_dir"; "/new/foo/bar"]];
1266     InitBasicFS, Always, TestOutputTrue
1267       [["mkdir_p"; "/new/foo/bar"];
1268        ["is_dir"; "/new/foo"]];
1269     InitBasicFS, Always, TestOutputTrue
1270       [["mkdir_p"; "/new/foo/bar"];
1271        ["is_dir"; "/new"]];
1272     (* Regression tests for RHBZ#503133: *)
1273     InitBasicFS, Always, TestRun
1274       [["mkdir"; "/new"];
1275        ["mkdir_p"; "/new"]];
1276     InitBasicFS, Always, TestLastFail
1277       [["touch"; "/new"];
1278        ["mkdir_p"; "/new"]]],
1279    "create a directory and parents",
1280    "\
1281 Create a directory named C<path>, creating any parent directories
1282 as necessary.  This is like the C<mkdir -p> shell command.");
1283
1284   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1285    [], (* XXX Need stat command to test *)
1286    "change file mode",
1287    "\
1288 Change the mode (permissions) of C<path> to C<mode>.  Only
1289 numeric modes are supported.");
1290
1291   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1292    [], (* XXX Need stat command to test *)
1293    "change file owner and group",
1294    "\
1295 Change the file owner to C<owner> and group to C<group>.
1296
1297 Only numeric uid and gid are supported.  If you want to use
1298 names, you will need to locate and parse the password file
1299 yourself (Augeas support makes this relatively easy).");
1300
1301   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1302    [InitISOFS, Always, TestOutputTrue (
1303       [["exists"; "/empty"]]);
1304     InitISOFS, Always, TestOutputTrue (
1305       [["exists"; "/directory"]])],
1306    "test if file or directory exists",
1307    "\
1308 This returns C<true> if and only if there is a file, directory
1309 (or anything) with the given C<path> name.
1310
1311 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1312
1313   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1314    [InitISOFS, Always, TestOutputTrue (
1315       [["is_file"; "/known-1"]]);
1316     InitISOFS, Always, TestOutputFalse (
1317       [["is_file"; "/directory"]])],
1318    "test if file exists",
1319    "\
1320 This returns C<true> if and only if there is a file
1321 with the given C<path> name.  Note that it returns false for
1322 other objects like directories.
1323
1324 See also C<guestfs_stat>.");
1325
1326   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1327    [InitISOFS, Always, TestOutputFalse (
1328       [["is_dir"; "/known-3"]]);
1329     InitISOFS, Always, TestOutputTrue (
1330       [["is_dir"; "/directory"]])],
1331    "test if file exists",
1332    "\
1333 This returns C<true> if and only if there is a directory
1334 with the given C<path> name.  Note that it returns false for
1335 other objects like files.
1336
1337 See also C<guestfs_stat>.");
1338
1339   ("pvcreate", (RErr, [Device "device"]), 39, [],
1340    [InitEmpty, Always, TestOutputListOfDevices (
1341       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1342        ["pvcreate"; "/dev/sda1"];
1343        ["pvcreate"; "/dev/sda2"];
1344        ["pvcreate"; "/dev/sda3"];
1345        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1346    "create an LVM physical volume",
1347    "\
1348 This creates an LVM physical volume on the named C<device>,
1349 where C<device> should usually be a partition name such
1350 as C</dev/sda1>.");
1351
1352   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [],
1353    [InitEmpty, Always, TestOutputList (
1354       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1355        ["pvcreate"; "/dev/sda1"];
1356        ["pvcreate"; "/dev/sda2"];
1357        ["pvcreate"; "/dev/sda3"];
1358        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1359        ["vgcreate"; "VG2"; "/dev/sda3"];
1360        ["vgs"]], ["VG1"; "VG2"])],
1361    "create an LVM volume group",
1362    "\
1363 This creates an LVM volume group called C<volgroup>
1364 from the non-empty list of physical volumes C<physvols>.");
1365
1366   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [],
1367    [InitEmpty, Always, TestOutputList (
1368       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1369        ["pvcreate"; "/dev/sda1"];
1370        ["pvcreate"; "/dev/sda2"];
1371        ["pvcreate"; "/dev/sda3"];
1372        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1373        ["vgcreate"; "VG2"; "/dev/sda3"];
1374        ["lvcreate"; "LV1"; "VG1"; "50"];
1375        ["lvcreate"; "LV2"; "VG1"; "50"];
1376        ["lvcreate"; "LV3"; "VG2"; "50"];
1377        ["lvcreate"; "LV4"; "VG2"; "50"];
1378        ["lvcreate"; "LV5"; "VG2"; "50"];
1379        ["lvs"]],
1380       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1381        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1382    "create an LVM volume group",
1383    "\
1384 This creates an LVM volume group called C<logvol>
1385 on the volume group C<volgroup>, with C<size> megabytes.");
1386
1387   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1388    [InitEmpty, Always, TestOutput (
1389       [["sfdiskM"; "/dev/sda"; ","];
1390        ["mkfs"; "ext2"; "/dev/sda1"];
1391        ["mount"; "/dev/sda1"; "/"];
1392        ["write_file"; "/new"; "new file contents"; "0"];
1393        ["cat"; "/new"]], "new file contents")],
1394    "make a filesystem",
1395    "\
1396 This creates a filesystem on C<device> (usually a partition
1397 or LVM logical volume).  The filesystem type is C<fstype>, for
1398 example C<ext3>.");
1399
1400   ("sfdisk", (RErr, [Device "device";
1401                      Int "cyls"; Int "heads"; Int "sectors";
1402                      StringList "lines"]), 43, [DangerWillRobinson],
1403    [],
1404    "create partitions on a block device",
1405    "\
1406 This is a direct interface to the L<sfdisk(8)> program for creating
1407 partitions on block devices.
1408
1409 C<device> should be a block device, for example C</dev/sda>.
1410
1411 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1412 and sectors on the device, which are passed directly to sfdisk as
1413 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1414 of these, then the corresponding parameter is omitted.  Usually for
1415 'large' disks, you can just pass C<0> for these, but for small
1416 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1417 out the right geometry and you will need to tell it.
1418
1419 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1420 information refer to the L<sfdisk(8)> manpage.
1421
1422 To create a single partition occupying the whole disk, you would
1423 pass C<lines> as a single element list, when the single element being
1424 the string C<,> (comma).
1425
1426 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>");
1427
1428   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1429    [InitBasicFS, Always, TestOutput (
1430       [["write_file"; "/new"; "new file contents"; "0"];
1431        ["cat"; "/new"]], "new file contents");
1432     InitBasicFS, Always, TestOutput (
1433       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1434        ["cat"; "/new"]], "\nnew file contents\n");
1435     InitBasicFS, Always, TestOutput (
1436       [["write_file"; "/new"; "\n\n"; "0"];
1437        ["cat"; "/new"]], "\n\n");
1438     InitBasicFS, Always, TestOutput (
1439       [["write_file"; "/new"; ""; "0"];
1440        ["cat"; "/new"]], "");
1441     InitBasicFS, Always, TestOutput (
1442       [["write_file"; "/new"; "\n\n\n"; "0"];
1443        ["cat"; "/new"]], "\n\n\n");
1444     InitBasicFS, Always, TestOutput (
1445       [["write_file"; "/new"; "\n"; "0"];
1446        ["cat"; "/new"]], "\n")],
1447    "create a file",
1448    "\
1449 This call creates a file called C<path>.  The contents of the
1450 file is the string C<content> (which can contain any 8 bit data),
1451 with length C<size>.
1452
1453 As a special case, if C<size> is C<0>
1454 then the length is calculated using C<strlen> (so in this case
1455 the content cannot contain embedded ASCII NULs).
1456
1457 I<NB.> Owing to a bug, writing content containing ASCII NUL
1458 characters does I<not> work, even if the length is specified.
1459 We hope to resolve this bug in a future version.  In the meantime
1460 use C<guestfs_upload>.");
1461
1462   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1463    [InitEmpty, Always, TestOutputListOfDevices (
1464       [["sfdiskM"; "/dev/sda"; ","];
1465        ["mkfs"; "ext2"; "/dev/sda1"];
1466        ["mount"; "/dev/sda1"; "/"];
1467        ["mounts"]], ["/dev/sda1"]);
1468     InitEmpty, Always, TestOutputList (
1469       [["sfdiskM"; "/dev/sda"; ","];
1470        ["mkfs"; "ext2"; "/dev/sda1"];
1471        ["mount"; "/dev/sda1"; "/"];
1472        ["umount"; "/"];
1473        ["mounts"]], [])],
1474    "unmount a filesystem",
1475    "\
1476 This unmounts the given filesystem.  The filesystem may be
1477 specified either by its mountpoint (path) or the device which
1478 contains the filesystem.");
1479
1480   ("mounts", (RStringList "devices", []), 46, [],
1481    [InitBasicFS, Always, TestOutputListOfDevices (
1482       [["mounts"]], ["/dev/sda1"])],
1483    "show mounted filesystems",
1484    "\
1485 This returns the list of currently mounted filesystems.  It returns
1486 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1487
1488 Some internal mounts are not shown.
1489
1490 See also: C<guestfs_mountpoints>");
1491
1492   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1493    [InitBasicFS, Always, TestOutputList (
1494       [["umount_all"];
1495        ["mounts"]], []);
1496     (* check that umount_all can unmount nested mounts correctly: *)
1497     InitEmpty, Always, TestOutputList (
1498       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1499        ["mkfs"; "ext2"; "/dev/sda1"];
1500        ["mkfs"; "ext2"; "/dev/sda2"];
1501        ["mkfs"; "ext2"; "/dev/sda3"];
1502        ["mount"; "/dev/sda1"; "/"];
1503        ["mkdir"; "/mp1"];
1504        ["mount"; "/dev/sda2"; "/mp1"];
1505        ["mkdir"; "/mp1/mp2"];
1506        ["mount"; "/dev/sda3"; "/mp1/mp2"];
1507        ["mkdir"; "/mp1/mp2/mp3"];
1508        ["umount_all"];
1509        ["mounts"]], [])],
1510    "unmount all filesystems",
1511    "\
1512 This unmounts all mounted filesystems.
1513
1514 Some internal mounts are not unmounted by this call.");
1515
1516   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson],
1517    [],
1518    "remove all LVM LVs, VGs and PVs",
1519    "\
1520 This command removes all LVM logical volumes, volume groups
1521 and physical volumes.");
1522
1523   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1524    [InitISOFS, Always, TestOutput (
1525       [["file"; "/empty"]], "empty");
1526     InitISOFS, Always, TestOutput (
1527       [["file"; "/known-1"]], "ASCII text");
1528     InitISOFS, Always, TestLastFail (
1529       [["file"; "/notexists"]])],
1530    "determine file type",
1531    "\
1532 This call uses the standard L<file(1)> command to determine
1533 the type or contents of the file.  This also works on devices,
1534 for example to find out whether a partition contains a filesystem.
1535
1536 This call will also transparently look inside various types
1537 of compressed file.
1538
1539 The exact command which runs is C<file -zbsL path>.  Note in
1540 particular that the filename is not prepended to the output
1541 (the C<-b> option).");
1542
1543   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1544    [InitBasicFS, Always, TestOutput (
1545       [["upload"; "test-command"; "/test-command"];
1546        ["chmod"; "0o755"; "/test-command"];
1547        ["command"; "/test-command 1"]], "Result1");
1548     InitBasicFS, Always, TestOutput (
1549       [["upload"; "test-command"; "/test-command"];
1550        ["chmod"; "0o755"; "/test-command"];
1551        ["command"; "/test-command 2"]], "Result2\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["upload"; "test-command"; "/test-command"];
1554        ["chmod"; "0o755"; "/test-command"];
1555        ["command"; "/test-command 3"]], "\nResult3");
1556     InitBasicFS, Always, TestOutput (
1557       [["upload"; "test-command"; "/test-command"];
1558        ["chmod"; "0o755"; "/test-command"];
1559        ["command"; "/test-command 4"]], "\nResult4\n");
1560     InitBasicFS, Always, TestOutput (
1561       [["upload"; "test-command"; "/test-command"];
1562        ["chmod"; "0o755"; "/test-command"];
1563        ["command"; "/test-command 5"]], "\nResult5\n\n");
1564     InitBasicFS, Always, TestOutput (
1565       [["upload"; "test-command"; "/test-command"];
1566        ["chmod"; "0o755"; "/test-command"];
1567        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1568     InitBasicFS, Always, TestOutput (
1569       [["upload"; "test-command"; "/test-command"];
1570        ["chmod"; "0o755"; "/test-command"];
1571        ["command"; "/test-command 7"]], "");
1572     InitBasicFS, Always, TestOutput (
1573       [["upload"; "test-command"; "/test-command"];
1574        ["chmod"; "0o755"; "/test-command"];
1575        ["command"; "/test-command 8"]], "\n");
1576     InitBasicFS, Always, TestOutput (
1577       [["upload"; "test-command"; "/test-command"];
1578        ["chmod"; "0o755"; "/test-command"];
1579        ["command"; "/test-command 9"]], "\n\n");
1580     InitBasicFS, Always, TestOutput (
1581       [["upload"; "test-command"; "/test-command"];
1582        ["chmod"; "0o755"; "/test-command"];
1583        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1584     InitBasicFS, Always, TestOutput (
1585       [["upload"; "test-command"; "/test-command"];
1586        ["chmod"; "0o755"; "/test-command"];
1587        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1588     InitBasicFS, Always, TestLastFail (
1589       [["upload"; "test-command"; "/test-command"];
1590        ["chmod"; "0o755"; "/test-command"];
1591        ["command"; "/test-command"]])],
1592    "run a command from the guest filesystem",
1593    "\
1594 This call runs a command from the guest filesystem.  The
1595 filesystem must be mounted, and must contain a compatible
1596 operating system (ie. something Linux, with the same
1597 or compatible processor architecture).
1598
1599 The single parameter is an argv-style list of arguments.
1600 The first element is the name of the program to run.
1601 Subsequent elements are parameters.  The list must be
1602 non-empty (ie. must contain a program name).  Note that
1603 the command runs directly, and is I<not> invoked via
1604 the shell (see C<guestfs_sh>).
1605
1606 The return value is anything printed to I<stdout> by
1607 the command.
1608
1609 If the command returns a non-zero exit status, then
1610 this function returns an error message.  The error message
1611 string is the content of I<stderr> from the command.
1612
1613 The C<$PATH> environment variable will contain at least
1614 C</usr/bin> and C</bin>.  If you require a program from
1615 another location, you should provide the full path in the
1616 first parameter.
1617
1618 Shared libraries and data files required by the program
1619 must be available on filesystems which are mounted in the
1620 correct places.  It is the caller's responsibility to ensure
1621 all filesystems that are needed are mounted at the right
1622 locations.");
1623
1624   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1625    [InitBasicFS, Always, TestOutputList (
1626       [["upload"; "test-command"; "/test-command"];
1627        ["chmod"; "0o755"; "/test-command"];
1628        ["command_lines"; "/test-command 1"]], ["Result1"]);
1629     InitBasicFS, Always, TestOutputList (
1630       [["upload"; "test-command"; "/test-command"];
1631        ["chmod"; "0o755"; "/test-command"];
1632        ["command_lines"; "/test-command 2"]], ["Result2"]);
1633     InitBasicFS, Always, TestOutputList (
1634       [["upload"; "test-command"; "/test-command"];
1635        ["chmod"; "0o755"; "/test-command"];
1636        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1637     InitBasicFS, Always, TestOutputList (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1641     InitBasicFS, Always, TestOutputList (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1645     InitBasicFS, Always, TestOutputList (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1649     InitBasicFS, Always, TestOutputList (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command_lines"; "/test-command 7"]], []);
1653     InitBasicFS, Always, TestOutputList (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command_lines"; "/test-command 8"]], [""]);
1657     InitBasicFS, Always, TestOutputList (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command_lines"; "/test-command 9"]], ["";""]);
1661     InitBasicFS, Always, TestOutputList (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1665     InitBasicFS, Always, TestOutputList (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1669    "run a command, returning lines",
1670    "\
1671 This is the same as C<guestfs_command>, but splits the
1672 result into a list of lines.
1673
1674 See also: C<guestfs_sh_lines>");
1675
1676   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1677    [InitISOFS, Always, TestOutputStruct (
1678       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1679    "get file information",
1680    "\
1681 Returns file information for the given C<path>.
1682
1683 This is the same as the C<stat(2)> system call.");
1684
1685   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1686    [InitISOFS, Always, TestOutputStruct (
1687       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1688    "get file information for a symbolic link",
1689    "\
1690 Returns file information for the given C<path>.
1691
1692 This is the same as C<guestfs_stat> except that if C<path>
1693 is a symbolic link, then the link is stat-ed, not the file it
1694 refers to.
1695
1696 This is the same as the C<lstat(2)> system call.");
1697
1698   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1699    [InitISOFS, Always, TestOutputStruct (
1700       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1701    "get file system statistics",
1702    "\
1703 Returns file system statistics for any mounted file system.
1704 C<path> should be a file or directory in the mounted file system
1705 (typically it is the mount point itself, but it doesn't need to be).
1706
1707 This is the same as the C<statvfs(2)> system call.");
1708
1709   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1710    [], (* XXX test *)
1711    "get ext2/ext3/ext4 superblock details",
1712    "\
1713 This returns the contents of the ext2, ext3 or ext4 filesystem
1714 superblock on C<device>.
1715
1716 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1717 manpage for more details.  The list of fields returned isn't
1718 clearly defined, and depends on both the version of C<tune2fs>
1719 that libguestfs was built against, and the filesystem itself.");
1720
1721   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1722    [InitEmpty, Always, TestOutputTrue (
1723       [["blockdev_setro"; "/dev/sda"];
1724        ["blockdev_getro"; "/dev/sda"]])],
1725    "set block device to read-only",
1726    "\
1727 Sets the block device named C<device> to read-only.
1728
1729 This uses the L<blockdev(8)> command.");
1730
1731   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1732    [InitEmpty, Always, TestOutputFalse (
1733       [["blockdev_setrw"; "/dev/sda"];
1734        ["blockdev_getro"; "/dev/sda"]])],
1735    "set block device to read-write",
1736    "\
1737 Sets the block device named C<device> to read-write.
1738
1739 This uses the L<blockdev(8)> command.");
1740
1741   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1742    [InitEmpty, Always, TestOutputTrue (
1743       [["blockdev_setro"; "/dev/sda"];
1744        ["blockdev_getro"; "/dev/sda"]])],
1745    "is block device set to read-only",
1746    "\
1747 Returns a boolean indicating if the block device is read-only
1748 (true if read-only, false if not).
1749
1750 This uses the L<blockdev(8)> command.");
1751
1752   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1753    [InitEmpty, Always, TestOutputInt (
1754       [["blockdev_getss"; "/dev/sda"]], 512)],
1755    "get sectorsize of block device",
1756    "\
1757 This returns the size of sectors on a block device.
1758 Usually 512, but can be larger for modern devices.
1759
1760 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1761 for that).
1762
1763 This uses the L<blockdev(8)> command.");
1764
1765   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1766    [InitEmpty, Always, TestOutputInt (
1767       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1768    "get blocksize of block device",
1769    "\
1770 This returns the block size of a device.
1771
1772 (Note this is different from both I<size in blocks> and
1773 I<filesystem block size>).
1774
1775 This uses the L<blockdev(8)> command.");
1776
1777   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1778    [], (* XXX test *)
1779    "set blocksize of block device",
1780    "\
1781 This sets the block size of a device.
1782
1783 (Note this is different from both I<size in blocks> and
1784 I<filesystem block size>).
1785
1786 This uses the L<blockdev(8)> command.");
1787
1788   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1789    [InitEmpty, Always, TestOutputInt (
1790       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1791    "get total size of device in 512-byte sectors",
1792    "\
1793 This returns the size of the device in units of 512-byte sectors
1794 (even if the sectorsize isn't 512 bytes ... weird).
1795
1796 See also C<guestfs_blockdev_getss> for the real sector size of
1797 the device, and C<guestfs_blockdev_getsize64> for the more
1798 useful I<size in bytes>.
1799
1800 This uses the L<blockdev(8)> command.");
1801
1802   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1803    [InitEmpty, Always, TestOutputInt (
1804       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1805    "get total size of device in bytes",
1806    "\
1807 This returns the size of the device in bytes.
1808
1809 See also C<guestfs_blockdev_getsz>.
1810
1811 This uses the L<blockdev(8)> command.");
1812
1813   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1814    [InitEmpty, Always, TestRun
1815       [["blockdev_flushbufs"; "/dev/sda"]]],
1816    "flush device buffers",
1817    "\
1818 This tells the kernel to flush internal buffers associated
1819 with C<device>.
1820
1821 This uses the L<blockdev(8)> command.");
1822
1823   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1824    [InitEmpty, Always, TestRun
1825       [["blockdev_rereadpt"; "/dev/sda"]]],
1826    "reread partition table",
1827    "\
1828 Reread the partition table on C<device>.
1829
1830 This uses the L<blockdev(8)> command.");
1831
1832   ("upload", (RErr, [FileIn "filename"; String "remotefilename"]), 66, [],
1833    [InitBasicFS, Always, TestOutput (
1834       (* Pick a file from cwd which isn't likely to change. *)
1835       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1836        ["checksum"; "md5"; "/COPYING.LIB"]],
1837         Digest.to_hex (Digest.file "COPYING.LIB"))],
1838    "upload a file from the local machine",
1839    "\
1840 Upload local file C<filename> to C<remotefilename> on the
1841 filesystem.
1842
1843 C<filename> can also be a named pipe.
1844
1845 See also C<guestfs_download>.");
1846
1847   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1848    [InitBasicFS, Always, TestOutput (
1849       (* Pick a file from cwd which isn't likely to change. *)
1850       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1851        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1852        ["upload"; "testdownload.tmp"; "/upload"];
1853        ["checksum"; "md5"; "/upload"]],
1854         Digest.to_hex (Digest.file "COPYING.LIB"))],
1855    "download a file to the local machine",
1856    "\
1857 Download file C<remotefilename> and save it as C<filename>
1858 on the local machine.
1859
1860 C<filename> can also be a named pipe.
1861
1862 See also C<guestfs_upload>, C<guestfs_cat>.");
1863
1864   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1865    [InitISOFS, Always, TestOutput (
1866       [["checksum"; "crc"; "/known-3"]], "2891671662");
1867     InitISOFS, Always, TestLastFail (
1868       [["checksum"; "crc"; "/notexists"]]);
1869     InitISOFS, Always, TestOutput (
1870       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1871     InitISOFS, Always, TestOutput (
1872       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1873     InitISOFS, Always, TestOutput (
1874       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1875     InitISOFS, Always, TestOutput (
1876       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1877     InitISOFS, Always, TestOutput (
1878       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1879     InitISOFS, Always, TestOutput (
1880       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1881    "compute MD5, SHAx or CRC checksum of file",
1882    "\
1883 This call computes the MD5, SHAx or CRC checksum of the
1884 file named C<path>.
1885
1886 The type of checksum to compute is given by the C<csumtype>
1887 parameter which must have one of the following values:
1888
1889 =over 4
1890
1891 =item C<crc>
1892
1893 Compute the cyclic redundancy check (CRC) specified by POSIX
1894 for the C<cksum> command.
1895
1896 =item C<md5>
1897
1898 Compute the MD5 hash (using the C<md5sum> program).
1899
1900 =item C<sha1>
1901
1902 Compute the SHA1 hash (using the C<sha1sum> program).
1903
1904 =item C<sha224>
1905
1906 Compute the SHA224 hash (using the C<sha224sum> program).
1907
1908 =item C<sha256>
1909
1910 Compute the SHA256 hash (using the C<sha256sum> program).
1911
1912 =item C<sha384>
1913
1914 Compute the SHA384 hash (using the C<sha384sum> program).
1915
1916 =item C<sha512>
1917
1918 Compute the SHA512 hash (using the C<sha512sum> program).
1919
1920 =back
1921
1922 The checksum is returned as a printable string.");
1923
1924   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
1925    [InitBasicFS, Always, TestOutput (
1926       [["tar_in"; "../images/helloworld.tar"; "/"];
1927        ["cat"; "/hello"]], "hello\n")],
1928    "unpack tarfile to directory",
1929    "\
1930 This command uploads and unpacks local file C<tarfile> (an
1931 I<uncompressed> tar file) into C<directory>.
1932
1933 To upload a compressed tarball, use C<guestfs_tgz_in>.");
1934
1935   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
1936    [],
1937    "pack directory into tarfile",
1938    "\
1939 This command packs the contents of C<directory> and downloads
1940 it to local file C<tarfile>.
1941
1942 To download a compressed tarball, use C<guestfs_tgz_out>.");
1943
1944   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
1945    [InitBasicFS, Always, TestOutput (
1946       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
1947        ["cat"; "/hello"]], "hello\n")],
1948    "unpack compressed tarball to directory",
1949    "\
1950 This command uploads and unpacks local file C<tarball> (a
1951 I<gzip compressed> tar file) into C<directory>.
1952
1953 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
1954
1955   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
1956    [],
1957    "pack directory into compressed tarball",
1958    "\
1959 This command packs the contents of C<directory> and downloads
1960 it to local file C<tarball>.
1961
1962 To download an uncompressed tarball, use C<guestfs_tar_out>.");
1963
1964   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
1965    [InitBasicFS, Always, TestLastFail (
1966       [["umount"; "/"];
1967        ["mount_ro"; "/dev/sda1"; "/"];
1968        ["touch"; "/new"]]);
1969     InitBasicFS, Always, TestOutput (
1970       [["write_file"; "/new"; "data"; "0"];
1971        ["umount"; "/"];
1972        ["mount_ro"; "/dev/sda1"; "/"];
1973        ["cat"; "/new"]], "data")],
1974    "mount a guest disk, read-only",
1975    "\
1976 This is the same as the C<guestfs_mount> command, but it
1977 mounts the filesystem with the read-only (I<-o ro>) flag.");
1978
1979   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
1980    [],
1981    "mount a guest disk with mount options",
1982    "\
1983 This is the same as the C<guestfs_mount> command, but it
1984 allows you to set the mount options as for the
1985 L<mount(8)> I<-o> flag.");
1986
1987   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
1988    [],
1989    "mount a guest disk with mount options and vfstype",
1990    "\
1991 This is the same as the C<guestfs_mount> command, but it
1992 allows you to set both the mount options and the vfstype
1993 as for the L<mount(8)> I<-o> and I<-t> flags.");
1994
1995   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
1996    [],
1997    "debugging and internals",
1998    "\
1999 The C<guestfs_debug> command exposes some internals of
2000 C<guestfsd> (the guestfs daemon) that runs inside the
2001 qemu subprocess.
2002
2003 There is no comprehensive help for this command.  You have
2004 to look at the file C<daemon/debug.c> in the libguestfs source
2005 to find out what you can do.");
2006
2007   ("lvremove", (RErr, [Device "device"]), 77, [],
2008    [InitEmpty, Always, TestOutputList (
2009       [["sfdiskM"; "/dev/sda"; ","];
2010        ["pvcreate"; "/dev/sda1"];
2011        ["vgcreate"; "VG"; "/dev/sda1"];
2012        ["lvcreate"; "LV1"; "VG"; "50"];
2013        ["lvcreate"; "LV2"; "VG"; "50"];
2014        ["lvremove"; "/dev/VG/LV1"];
2015        ["lvs"]], ["/dev/VG/LV2"]);
2016     InitEmpty, Always, TestOutputList (
2017       [["sfdiskM"; "/dev/sda"; ","];
2018        ["pvcreate"; "/dev/sda1"];
2019        ["vgcreate"; "VG"; "/dev/sda1"];
2020        ["lvcreate"; "LV1"; "VG"; "50"];
2021        ["lvcreate"; "LV2"; "VG"; "50"];
2022        ["lvremove"; "/dev/VG"];
2023        ["lvs"]], []);
2024     InitEmpty, Always, TestOutputList (
2025       [["sfdiskM"; "/dev/sda"; ","];
2026        ["pvcreate"; "/dev/sda1"];
2027        ["vgcreate"; "VG"; "/dev/sda1"];
2028        ["lvcreate"; "LV1"; "VG"; "50"];
2029        ["lvcreate"; "LV2"; "VG"; "50"];
2030        ["lvremove"; "/dev/VG"];
2031        ["vgs"]], ["VG"])],
2032    "remove an LVM logical volume",
2033    "\
2034 Remove an LVM logical volume C<device>, where C<device> is
2035 the path to the LV, such as C</dev/VG/LV>.
2036
2037 You can also remove all LVs in a volume group by specifying
2038 the VG name, C</dev/VG>.");
2039
2040   ("vgremove", (RErr, [String "vgname"]), 78, [],
2041    [InitEmpty, Always, TestOutputList (
2042       [["sfdiskM"; "/dev/sda"; ","];
2043        ["pvcreate"; "/dev/sda1"];
2044        ["vgcreate"; "VG"; "/dev/sda1"];
2045        ["lvcreate"; "LV1"; "VG"; "50"];
2046        ["lvcreate"; "LV2"; "VG"; "50"];
2047        ["vgremove"; "VG"];
2048        ["lvs"]], []);
2049     InitEmpty, Always, TestOutputList (
2050       [["sfdiskM"; "/dev/sda"; ","];
2051        ["pvcreate"; "/dev/sda1"];
2052        ["vgcreate"; "VG"; "/dev/sda1"];
2053        ["lvcreate"; "LV1"; "VG"; "50"];
2054        ["lvcreate"; "LV2"; "VG"; "50"];
2055        ["vgremove"; "VG"];
2056        ["vgs"]], [])],
2057    "remove an LVM volume group",
2058    "\
2059 Remove an LVM volume group C<vgname>, (for example C<VG>).
2060
2061 This also forcibly removes all logical volumes in the volume
2062 group (if any).");
2063
2064   ("pvremove", (RErr, [Device "device"]), 79, [],
2065    [InitEmpty, Always, TestOutputListOfDevices (
2066       [["sfdiskM"; "/dev/sda"; ","];
2067        ["pvcreate"; "/dev/sda1"];
2068        ["vgcreate"; "VG"; "/dev/sda1"];
2069        ["lvcreate"; "LV1"; "VG"; "50"];
2070        ["lvcreate"; "LV2"; "VG"; "50"];
2071        ["vgremove"; "VG"];
2072        ["pvremove"; "/dev/sda1"];
2073        ["lvs"]], []);
2074     InitEmpty, Always, TestOutputListOfDevices (
2075       [["sfdiskM"; "/dev/sda"; ","];
2076        ["pvcreate"; "/dev/sda1"];
2077        ["vgcreate"; "VG"; "/dev/sda1"];
2078        ["lvcreate"; "LV1"; "VG"; "50"];
2079        ["lvcreate"; "LV2"; "VG"; "50"];
2080        ["vgremove"; "VG"];
2081        ["pvremove"; "/dev/sda1"];
2082        ["vgs"]], []);
2083     InitEmpty, Always, TestOutputListOfDevices (
2084       [["sfdiskM"; "/dev/sda"; ","];
2085        ["pvcreate"; "/dev/sda1"];
2086        ["vgcreate"; "VG"; "/dev/sda1"];
2087        ["lvcreate"; "LV1"; "VG"; "50"];
2088        ["lvcreate"; "LV2"; "VG"; "50"];
2089        ["vgremove"; "VG"];
2090        ["pvremove"; "/dev/sda1"];
2091        ["pvs"]], [])],
2092    "remove an LVM physical volume",
2093    "\
2094 This wipes a physical volume C<device> so that LVM will no longer
2095 recognise it.
2096
2097 The implementation uses the C<pvremove> command which refuses to
2098 wipe physical volumes that contain any volume groups, so you have
2099 to remove those first.");
2100
2101   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2102    [InitBasicFS, Always, TestOutput (
2103       [["set_e2label"; "/dev/sda1"; "testlabel"];
2104        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2105    "set the ext2/3/4 filesystem label",
2106    "\
2107 This sets the ext2/3/4 filesystem label of the filesystem on
2108 C<device> to C<label>.  Filesystem labels are limited to
2109 16 characters.
2110
2111 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2112 to return the existing label on a filesystem.");
2113
2114   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2115    [],
2116    "get the ext2/3/4 filesystem label",
2117    "\
2118 This returns the ext2/3/4 filesystem label of the filesystem on
2119 C<device>.");
2120
2121   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2122    (let uuid = uuidgen () in
2123     [InitBasicFS, Always, TestOutput (
2124        [["set_e2uuid"; "/dev/sda1"; uuid];
2125         ["get_e2uuid"; "/dev/sda1"]], uuid);
2126      InitBasicFS, Always, TestOutput (
2127        [["set_e2uuid"; "/dev/sda1"; "clear"];
2128         ["get_e2uuid"; "/dev/sda1"]], "");
2129      (* We can't predict what UUIDs will be, so just check the commands run. *)
2130      InitBasicFS, Always, TestRun (
2131        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2132      InitBasicFS, Always, TestRun (
2133        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2134    "set the ext2/3/4 filesystem UUID",
2135    "\
2136 This sets the ext2/3/4 filesystem UUID of the filesystem on
2137 C<device> to C<uuid>.  The format of the UUID and alternatives
2138 such as C<clear>, C<random> and C<time> are described in the
2139 L<tune2fs(8)> manpage.
2140
2141 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2142 to return the existing UUID of a filesystem.");
2143
2144   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2145    [],
2146    "get the ext2/3/4 filesystem UUID",
2147    "\
2148 This returns the ext2/3/4 filesystem UUID of the filesystem on
2149 C<device>.");
2150
2151   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2152    [InitBasicFS, Always, TestOutputInt (
2153       [["umount"; "/dev/sda1"];
2154        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2155     InitBasicFS, Always, TestOutputInt (
2156       [["umount"; "/dev/sda1"];
2157        ["zero"; "/dev/sda1"];
2158        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2159    "run the filesystem checker",
2160    "\
2161 This runs the filesystem checker (fsck) on C<device> which
2162 should have filesystem type C<fstype>.
2163
2164 The returned integer is the status.  See L<fsck(8)> for the
2165 list of status codes from C<fsck>.
2166
2167 Notes:
2168
2169 =over 4
2170
2171 =item *
2172
2173 Multiple status codes can be summed together.
2174
2175 =item *
2176
2177 A non-zero return code can mean \"success\", for example if
2178 errors have been corrected on the filesystem.
2179
2180 =item *
2181
2182 Checking or repairing NTFS volumes is not supported
2183 (by linux-ntfs).
2184
2185 =back
2186
2187 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2188
2189   ("zero", (RErr, [Device "device"]), 85, [],
2190    [InitBasicFS, Always, TestOutput (
2191       [["umount"; "/dev/sda1"];
2192        ["zero"; "/dev/sda1"];
2193        ["file"; "/dev/sda1"]], "data")],
2194    "write zeroes to the device",
2195    "\
2196 This command writes zeroes over the first few blocks of C<device>.
2197
2198 How many blocks are zeroed isn't specified (but it's I<not> enough
2199 to securely wipe the device).  It should be sufficient to remove
2200 any partition tables, filesystem superblocks and so on.
2201
2202 See also: C<guestfs_scrub_device>.");
2203
2204   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2205    (* Test disabled because grub-install incompatible with virtio-blk driver.
2206     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2207     *)
2208    [InitBasicFS, Disabled, TestOutputTrue (
2209       [["grub_install"; "/"; "/dev/sda1"];
2210        ["is_dir"; "/boot"]])],
2211    "install GRUB",
2212    "\
2213 This command installs GRUB (the Grand Unified Bootloader) on
2214 C<device>, with the root directory being C<root>.");
2215
2216   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2217    [InitBasicFS, Always, TestOutput (
2218       [["write_file"; "/old"; "file content"; "0"];
2219        ["cp"; "/old"; "/new"];
2220        ["cat"; "/new"]], "file content");
2221     InitBasicFS, Always, TestOutputTrue (
2222       [["write_file"; "/old"; "file content"; "0"];
2223        ["cp"; "/old"; "/new"];
2224        ["is_file"; "/old"]]);
2225     InitBasicFS, Always, TestOutput (
2226       [["write_file"; "/old"; "file content"; "0"];
2227        ["mkdir"; "/dir"];
2228        ["cp"; "/old"; "/dir/new"];
2229        ["cat"; "/dir/new"]], "file content")],
2230    "copy a file",
2231    "\
2232 This copies a file from C<src> to C<dest> where C<dest> is
2233 either a destination filename or destination directory.");
2234
2235   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2236    [InitBasicFS, Always, TestOutput (
2237       [["mkdir"; "/olddir"];
2238        ["mkdir"; "/newdir"];
2239        ["write_file"; "/olddir/file"; "file content"; "0"];
2240        ["cp_a"; "/olddir"; "/newdir"];
2241        ["cat"; "/newdir/olddir/file"]], "file content")],
2242    "copy a file or directory recursively",
2243    "\
2244 This copies a file or directory from C<src> to C<dest>
2245 recursively using the C<cp -a> command.");
2246
2247   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2248    [InitBasicFS, Always, TestOutput (
2249       [["write_file"; "/old"; "file content"; "0"];
2250        ["mv"; "/old"; "/new"];
2251        ["cat"; "/new"]], "file content");
2252     InitBasicFS, Always, TestOutputFalse (
2253       [["write_file"; "/old"; "file content"; "0"];
2254        ["mv"; "/old"; "/new"];
2255        ["is_file"; "/old"]])],
2256    "move a file",
2257    "\
2258 This moves a file from C<src> to C<dest> where C<dest> is
2259 either a destination filename or destination directory.");
2260
2261   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2262    [InitEmpty, Always, TestRun (
2263       [["drop_caches"; "3"]])],
2264    "drop kernel page cache, dentries and inodes",
2265    "\
2266 This instructs the guest kernel to drop its page cache,
2267 and/or dentries and inode caches.  The parameter C<whattodrop>
2268 tells the kernel what precisely to drop, see
2269 L<http://linux-mm.org/Drop_Caches>
2270
2271 Setting C<whattodrop> to 3 should drop everything.
2272
2273 This automatically calls L<sync(2)> before the operation,
2274 so that the maximum guest memory is freed.");
2275
2276   ("dmesg", (RString "kmsgs", []), 91, [],
2277    [InitEmpty, Always, TestRun (
2278       [["dmesg"]])],
2279    "return kernel messages",
2280    "\
2281 This returns the kernel messages (C<dmesg> output) from
2282 the guest kernel.  This is sometimes useful for extended
2283 debugging of problems.
2284
2285 Another way to get the same information is to enable
2286 verbose messages with C<guestfs_set_verbose> or by setting
2287 the environment variable C<LIBGUESTFS_DEBUG=1> before
2288 running the program.");
2289
2290   ("ping_daemon", (RErr, []), 92, [],
2291    [InitEmpty, Always, TestRun (
2292       [["ping_daemon"]])],
2293    "ping the guest daemon",
2294    "\
2295 This is a test probe into the guestfs daemon running inside
2296 the qemu subprocess.  Calling this function checks that the
2297 daemon responds to the ping message, without affecting the daemon
2298 or attached block device(s) in any other way.");
2299
2300   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2301    [InitBasicFS, Always, TestOutputTrue (
2302       [["write_file"; "/file1"; "contents of a file"; "0"];
2303        ["cp"; "/file1"; "/file2"];
2304        ["equal"; "/file1"; "/file2"]]);
2305     InitBasicFS, Always, TestOutputFalse (
2306       [["write_file"; "/file1"; "contents of a file"; "0"];
2307        ["write_file"; "/file2"; "contents of another file"; "0"];
2308        ["equal"; "/file1"; "/file2"]]);
2309     InitBasicFS, Always, TestLastFail (
2310       [["equal"; "/file1"; "/file2"]])],
2311    "test if two files have equal contents",
2312    "\
2313 This compares the two files C<file1> and C<file2> and returns
2314 true if their content is exactly equal, or false otherwise.
2315
2316 The external L<cmp(1)> program is used for the comparison.");
2317
2318   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2319    [InitISOFS, Always, TestOutputList (
2320       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2321     InitISOFS, Always, TestOutputList (
2322       [["strings"; "/empty"]], [])],
2323    "print the printable strings in a file",
2324    "\
2325 This runs the L<strings(1)> command on a file and returns
2326 the list of printable strings found.");
2327
2328   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2329    [InitISOFS, Always, TestOutputList (
2330       [["strings_e"; "b"; "/known-5"]], []);
2331     InitBasicFS, Disabled, TestOutputList (
2332       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2333        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2334    "print the printable strings in a file",
2335    "\
2336 This is like the C<guestfs_strings> command, but allows you to
2337 specify the encoding.
2338
2339 See the L<strings(1)> manpage for the full list of encodings.
2340
2341 Commonly useful encodings are C<l> (lower case L) which will
2342 show strings inside Windows/x86 files.
2343
2344 The returned strings are transcoded to UTF-8.");
2345
2346   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2347    [InitISOFS, Always, TestOutput (
2348       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2349     (* Test for RHBZ#501888c2 regression which caused large hexdump
2350      * commands to segfault.
2351      *)
2352     InitISOFS, Always, TestRun (
2353       [["hexdump"; "/100krandom"]])],
2354    "dump a file in hexadecimal",
2355    "\
2356 This runs C<hexdump -C> on the given C<path>.  The result is
2357 the human-readable, canonical hex dump of the file.");
2358
2359   ("zerofree", (RErr, [Device "device"]), 97, [],
2360    [InitNone, Always, TestOutput (
2361       [["sfdiskM"; "/dev/sda"; ","];
2362        ["mkfs"; "ext3"; "/dev/sda1"];
2363        ["mount"; "/dev/sda1"; "/"];
2364        ["write_file"; "/new"; "test file"; "0"];
2365        ["umount"; "/dev/sda1"];
2366        ["zerofree"; "/dev/sda1"];
2367        ["mount"; "/dev/sda1"; "/"];
2368        ["cat"; "/new"]], "test file")],
2369    "zero unused inodes and disk blocks on ext2/3 filesystem",
2370    "\
2371 This runs the I<zerofree> program on C<device>.  This program
2372 claims to zero unused inodes and disk blocks on an ext2/3
2373 filesystem, thus making it possible to compress the filesystem
2374 more effectively.
2375
2376 You should B<not> run this program if the filesystem is
2377 mounted.
2378
2379 It is possible that using this program can damage the filesystem
2380 or data on the filesystem.");
2381
2382   ("pvresize", (RErr, [Device "device"]), 98, [],
2383    [],
2384    "resize an LVM physical volume",
2385    "\
2386 This resizes (expands or shrinks) an existing LVM physical
2387 volume to match the new size of the underlying device.");
2388
2389   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2390                        Int "cyls"; Int "heads"; Int "sectors";
2391                        String "line"]), 99, [DangerWillRobinson],
2392    [],
2393    "modify a single partition on a block device",
2394    "\
2395 This runs L<sfdisk(8)> option to modify just the single
2396 partition C<n> (note: C<n> counts from 1).
2397
2398 For other parameters, see C<guestfs_sfdisk>.  You should usually
2399 pass C<0> for the cyls/heads/sectors parameters.");
2400
2401   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2402    [],
2403    "display the partition table",
2404    "\
2405 This displays the partition table on C<device>, in the
2406 human-readable output of the L<sfdisk(8)> command.  It is
2407 not intended to be parsed.");
2408
2409   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2410    [],
2411    "display the kernel geometry",
2412    "\
2413 This displays the kernel's idea of the geometry of C<device>.
2414
2415 The result is in human-readable format, and not designed to
2416 be parsed.");
2417
2418   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2419    [],
2420    "display the disk geometry from the partition table",
2421    "\
2422 This displays the disk geometry of C<device> read from the
2423 partition table.  Especially in the case where the underlying
2424 block device has been resized, this can be different from the
2425 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2426
2427 The result is in human-readable format, and not designed to
2428 be parsed.");
2429
2430   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [],
2431    [],
2432    "activate or deactivate all volume groups",
2433    "\
2434 This command activates or (if C<activate> is false) deactivates
2435 all logical volumes in all volume groups.
2436 If activated, then they are made known to the
2437 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2438 then those devices disappear.
2439
2440 This command is the same as running C<vgchange -a y|n>");
2441
2442   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [],
2443    [],
2444    "activate or deactivate some volume groups",
2445    "\
2446 This command activates or (if C<activate> is false) deactivates
2447 all logical volumes in the listed volume groups C<volgroups>.
2448 If activated, then they are made known to the
2449 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2450 then those devices disappear.
2451
2452 This command is the same as running C<vgchange -a y|n volgroups...>
2453
2454 Note that if C<volgroups> is an empty list then B<all> volume groups
2455 are activated or deactivated.");
2456
2457   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [],
2458    [InitNone, Always, TestOutput (
2459       [["sfdiskM"; "/dev/sda"; ","];
2460        ["pvcreate"; "/dev/sda1"];
2461        ["vgcreate"; "VG"; "/dev/sda1"];
2462        ["lvcreate"; "LV"; "VG"; "10"];
2463        ["mkfs"; "ext2"; "/dev/VG/LV"];
2464        ["mount"; "/dev/VG/LV"; "/"];
2465        ["write_file"; "/new"; "test content"; "0"];
2466        ["umount"; "/"];
2467        ["lvresize"; "/dev/VG/LV"; "20"];
2468        ["e2fsck_f"; "/dev/VG/LV"];
2469        ["resize2fs"; "/dev/VG/LV"];
2470        ["mount"; "/dev/VG/LV"; "/"];
2471        ["cat"; "/new"]], "test content")],
2472    "resize an LVM logical volume",
2473    "\
2474 This resizes (expands or shrinks) an existing LVM logical
2475 volume to C<mbytes>.  When reducing, data in the reduced part
2476 is lost.");
2477
2478   ("resize2fs", (RErr, [Device "device"]), 106, [],
2479    [], (* lvresize tests this *)
2480    "resize an ext2/ext3 filesystem",
2481    "\
2482 This resizes an ext2 or ext3 filesystem to match the size of
2483 the underlying device.
2484
2485 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2486 on the C<device> before calling this command.  For unknown reasons
2487 C<resize2fs> sometimes gives an error about this and sometimes not.
2488 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2489 calling this function.");
2490
2491   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2492    [InitBasicFS, Always, TestOutputList (
2493       [["find"; "/"]], ["lost+found"]);
2494     InitBasicFS, Always, TestOutputList (
2495       [["touch"; "/a"];
2496        ["mkdir"; "/b"];
2497        ["touch"; "/b/c"];
2498        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2499     InitBasicFS, Always, TestOutputList (
2500       [["mkdir_p"; "/a/b/c"];
2501        ["touch"; "/a/b/c/d"];
2502        ["find"; "/a/b/"]], ["c"; "c/d"])],
2503    "find all files and directories",
2504    "\
2505 This command lists out all files and directories, recursively,
2506 starting at C<directory>.  It is essentially equivalent to
2507 running the shell command C<find directory -print> but some
2508 post-processing happens on the output, described below.
2509
2510 This returns a list of strings I<without any prefix>.  Thus
2511 if the directory structure was:
2512
2513  /tmp/a
2514  /tmp/b
2515  /tmp/c/d
2516
2517 then the returned list from C<guestfs_find> C</tmp> would be
2518 4 elements:
2519
2520  a
2521  b
2522  c
2523  c/d
2524
2525 If C<directory> is not a directory, then this command returns
2526 an error.
2527
2528 The returned list is sorted.
2529
2530 See also C<guestfs_find0>.");
2531
2532   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2533    [], (* lvresize tests this *)
2534    "check an ext2/ext3 filesystem",
2535    "\
2536 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2537 filesystem checker on C<device>, noninteractively (C<-p>),
2538 even if the filesystem appears to be clean (C<-f>).
2539
2540 This command is only needed because of C<guestfs_resize2fs>
2541 (q.v.).  Normally you should use C<guestfs_fsck>.");
2542
2543   ("sleep", (RErr, [Int "secs"]), 109, [],
2544    [InitNone, Always, TestRun (
2545       [["sleep"; "1"]])],
2546    "sleep for some seconds",
2547    "\
2548 Sleep for C<secs> seconds.");
2549
2550   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [],
2551    [InitNone, Always, TestOutputInt (
2552       [["sfdiskM"; "/dev/sda"; ","];
2553        ["mkfs"; "ntfs"; "/dev/sda1"];
2554        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2555     InitNone, Always, TestOutputInt (
2556       [["sfdiskM"; "/dev/sda"; ","];
2557        ["mkfs"; "ext2"; "/dev/sda1"];
2558        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2559    "probe NTFS volume",
2560    "\
2561 This command runs the L<ntfs-3g.probe(8)> command which probes
2562 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2563 be mounted read-write, and some cannot be mounted at all).
2564
2565 C<rw> is a boolean flag.  Set it to true if you want to test
2566 if the volume can be mounted read-write.  Set it to false if
2567 you want to test if the volume can be mounted read-only.
2568
2569 The return value is an integer which C<0> if the operation
2570 would succeed, or some non-zero value documented in the
2571 L<ntfs-3g.probe(8)> manual page.");
2572
2573   ("sh", (RString "output", [String "command"]), 111, [],
2574    [], (* XXX needs tests *)
2575    "run a command via the shell",
2576    "\
2577 This call runs a command from the guest filesystem via the
2578 guest's C</bin/sh>.
2579
2580 This is like C<guestfs_command>, but passes the command to:
2581
2582  /bin/sh -c \"command\"
2583
2584 Depending on the guest's shell, this usually results in
2585 wildcards being expanded, shell expressions being interpolated
2586 and so on.
2587
2588 All the provisos about C<guestfs_command> apply to this call.");
2589
2590   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2591    [], (* XXX needs tests *)
2592    "run a command via the shell returning lines",
2593    "\
2594 This is the same as C<guestfs_sh>, but splits the result
2595 into a list of lines.
2596
2597 See also: C<guestfs_command_lines>");
2598
2599   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2600    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2601     * code in stubs.c, since all valid glob patterns must start with "/".
2602     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2603     *)
2604    [InitBasicFS, Always, TestOutputList (
2605       [["mkdir_p"; "/a/b/c"];
2606        ["touch"; "/a/b/c/d"];
2607        ["touch"; "/a/b/c/e"];
2608        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2609     InitBasicFS, Always, TestOutputList (
2610       [["mkdir_p"; "/a/b/c"];
2611        ["touch"; "/a/b/c/d"];
2612        ["touch"; "/a/b/c/e"];
2613        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2614     InitBasicFS, Always, TestOutputList (
2615       [["mkdir_p"; "/a/b/c"];
2616        ["touch"; "/a/b/c/d"];
2617        ["touch"; "/a/b/c/e"];
2618        ["glob_expand"; "/a/*/x/*"]], [])],
2619    "expand a wildcard path",
2620    "\
2621 This command searches for all the pathnames matching
2622 C<pattern> according to the wildcard expansion rules
2623 used by the shell.
2624
2625 If no paths match, then this returns an empty list
2626 (note: not an error).
2627
2628 It is just a wrapper around the C L<glob(3)> function
2629 with flags C<GLOB_MARK|GLOB_BRACE>.
2630 See that manual page for more details.");
2631
2632   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson],
2633    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2634       [["scrub_device"; "/dev/sdc"]])],
2635    "scrub (securely wipe) a device",
2636    "\
2637 This command writes patterns over C<device> to make data retrieval
2638 more difficult.
2639
2640 It is an interface to the L<scrub(1)> program.  See that
2641 manual page for more details.");
2642
2643   ("scrub_file", (RErr, [Pathname "file"]), 115, [],
2644    [InitBasicFS, Always, TestRun (
2645       [["write_file"; "/file"; "content"; "0"];
2646        ["scrub_file"; "/file"]])],
2647    "scrub (securely wipe) a file",
2648    "\
2649 This command writes patterns over a file to make data retrieval
2650 more difficult.
2651
2652 The file is I<removed> after scrubbing.
2653
2654 It is an interface to the L<scrub(1)> program.  See that
2655 manual page for more details.");
2656
2657   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [],
2658    [], (* XXX needs testing *)
2659    "scrub (securely wipe) free space",
2660    "\
2661 This command creates the directory C<dir> and then fills it
2662 with files until the filesystem is full, and scrubs the files
2663 as for C<guestfs_scrub_file>, and deletes them.
2664 The intention is to scrub any free space on the partition
2665 containing C<dir>.
2666
2667 It is an interface to the L<scrub(1)> program.  See that
2668 manual page for more details.");
2669
2670   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2671    [InitBasicFS, Always, TestRun (
2672       [["mkdir"; "/tmp"];
2673        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2674    "create a temporary directory",
2675    "\
2676 This command creates a temporary directory.  The
2677 C<template> parameter should be a full pathname for the
2678 temporary directory name with the final six characters being
2679 \"XXXXXX\".
2680
2681 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2682 the second one being suitable for Windows filesystems.
2683
2684 The name of the temporary directory that was created
2685 is returned.
2686
2687 The temporary directory is created with mode 0700
2688 and is owned by root.
2689
2690 The caller is responsible for deleting the temporary
2691 directory and its contents after use.
2692
2693 See also: L<mkdtemp(3)>");
2694
2695   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2696    [InitISOFS, Always, TestOutputInt (
2697       [["wc_l"; "/10klines"]], 10000)],
2698    "count lines in a file",
2699    "\
2700 This command counts the lines in a file, using the
2701 C<wc -l> external command.");
2702
2703   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2704    [InitISOFS, Always, TestOutputInt (
2705       [["wc_w"; "/10klines"]], 10000)],
2706    "count words in a file",
2707    "\
2708 This command counts the words in a file, using the
2709 C<wc -w> external command.");
2710
2711   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2712    [InitISOFS, Always, TestOutputInt (
2713       [["wc_c"; "/100kallspaces"]], 102400)],
2714    "count characters in a file",
2715    "\
2716 This command counts the characters in a file, using the
2717 C<wc -c> external command.");
2718
2719   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2720    [InitISOFS, Always, TestOutputList (
2721       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2722    "return first 10 lines of a file",
2723    "\
2724 This command returns up to the first 10 lines of a file as
2725 a list of strings.");
2726
2727   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2728    [InitISOFS, Always, TestOutputList (
2729       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2730     InitISOFS, Always, TestOutputList (
2731       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2732     InitISOFS, Always, TestOutputList (
2733       [["head_n"; "0"; "/10klines"]], [])],
2734    "return first N lines of a file",
2735    "\
2736 If the parameter C<nrlines> is a positive number, this returns the first
2737 C<nrlines> lines of the file C<path>.
2738
2739 If the parameter C<nrlines> is a negative number, this returns lines
2740 from the file C<path>, excluding the last C<nrlines> lines.
2741
2742 If the parameter C<nrlines> is zero, this returns an empty list.");
2743
2744   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2745    [InitISOFS, Always, TestOutputList (
2746       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2747    "return last 10 lines of a file",
2748    "\
2749 This command returns up to the last 10 lines of a file as
2750 a list of strings.");
2751
2752   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2753    [InitISOFS, Always, TestOutputList (
2754       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2755     InitISOFS, Always, TestOutputList (
2756       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2757     InitISOFS, Always, TestOutputList (
2758       [["tail_n"; "0"; "/10klines"]], [])],
2759    "return last N lines of a file",
2760    "\
2761 If the parameter C<nrlines> is a positive number, this returns the last
2762 C<nrlines> lines of the file C<path>.
2763
2764 If the parameter C<nrlines> is a negative number, this returns lines
2765 from the file C<path>, starting with the C<-nrlines>th line.
2766
2767 If the parameter C<nrlines> is zero, this returns an empty list.");
2768
2769   ("df", (RString "output", []), 125, [],
2770    [], (* XXX Tricky to test because it depends on the exact format
2771         * of the 'df' command and other imponderables.
2772         *)
2773    "report file system disk space usage",
2774    "\
2775 This command runs the C<df> command to report disk space used.
2776
2777 This command is mostly useful for interactive sessions.  It
2778 is I<not> intended that you try to parse the output string.
2779 Use C<statvfs> from programs.");
2780
2781   ("df_h", (RString "output", []), 126, [],
2782    [], (* XXX Tricky to test because it depends on the exact format
2783         * of the 'df' command and other imponderables.
2784         *)
2785    "report file system disk space usage (human readable)",
2786    "\
2787 This command runs the C<df -h> command to report disk space used
2788 in human-readable format.
2789
2790 This command is mostly useful for interactive sessions.  It
2791 is I<not> intended that you try to parse the output string.
2792 Use C<statvfs> from programs.");
2793
2794   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2797    "estimate file space usage",
2798    "\
2799 This command runs the C<du -s> command to estimate file space
2800 usage for C<path>.
2801
2802 C<path> can be a file or a directory.  If C<path> is a directory
2803 then the estimate includes the contents of the directory and all
2804 subdirectories (recursively).
2805
2806 The result is the estimated size in I<kilobytes>
2807 (ie. units of 1024 bytes).");
2808
2809   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2810    [InitISOFS, Always, TestOutputList (
2811       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2812    "list files in an initrd",
2813    "\
2814 This command lists out files contained in an initrd.
2815
2816 The files are listed without any initial C</> character.  The
2817 files are listed in the order they appear (not necessarily
2818 alphabetical).  Directory names are listed as separate items.
2819
2820 Old Linux kernels (2.4 and earlier) used a compressed ext2
2821 filesystem as initrd.  We I<only> support the newer initramfs
2822 format (compressed cpio files).");
2823
2824   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2825    [],
2826    "mount a file using the loop device",
2827    "\
2828 This command lets you mount C<file> (a filesystem image
2829 in a file) on a mount point.  It is entirely equivalent to
2830 the command C<mount -o loop file mountpoint>.");
2831
2832   ("mkswap", (RErr, [Device "device"]), 130, [],
2833    [InitEmpty, Always, TestRun (
2834       [["sfdiskM"; "/dev/sda"; ","];
2835        ["mkswap"; "/dev/sda1"]])],
2836    "create a swap partition",
2837    "\
2838 Create a swap partition on C<device>.");
2839
2840   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2841    [InitEmpty, Always, TestRun (
2842       [["sfdiskM"; "/dev/sda"; ","];
2843        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2844    "create a swap partition with a label",
2845    "\
2846 Create a swap partition on C<device> with label C<label>.
2847
2848 Note that you cannot attach a swap label to a block device
2849 (eg. C</dev/sda>), just to a partition.  This appears to be
2850 a limitation of the kernel or swap tools.");
2851
2852   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [],
2853    (let uuid = uuidgen () in
2854     [InitEmpty, Always, TestRun (
2855        [["sfdiskM"; "/dev/sda"; ","];
2856         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2857    "create a swap partition with an explicit UUID",
2858    "\
2859 Create a swap partition on C<device> with UUID C<uuid>.");
2860
2861   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [],
2862    [InitBasicFS, Always, TestOutputStruct (
2863       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2864        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2865        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2866     InitBasicFS, Always, TestOutputStruct (
2867       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2868        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2869    "make block, character or FIFO devices",
2870    "\
2871 This call creates block or character special devices, or
2872 named pipes (FIFOs).
2873
2874 The C<mode> parameter should be the mode, using the standard
2875 constants.  C<devmajor> and C<devminor> are the
2876 device major and minor numbers, only used when creating block
2877 and character special devices.");
2878
2879   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [],
2880    [InitBasicFS, Always, TestOutputStruct (
2881       [["mkfifo"; "0o777"; "/node"];
2882        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2883    "make FIFO (named pipe)",
2884    "\
2885 This call creates a FIFO (named pipe) called C<path> with
2886 mode C<mode>.  It is just a convenient wrapper around
2887 C<guestfs_mknod>.");
2888
2889   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [],
2890    [InitBasicFS, Always, TestOutputStruct (
2891       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2892        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2893    "make block device node",
2894    "\
2895 This call creates a block device node called C<path> with
2896 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2897 It is just a convenient wrapper around C<guestfs_mknod>.");
2898
2899   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [],
2900    [InitBasicFS, Always, TestOutputStruct (
2901       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2902        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2903    "make char device node",
2904    "\
2905 This call creates a char device node called C<path> with
2906 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2907 It is just a convenient wrapper around C<guestfs_mknod>.");
2908
2909   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2910    [], (* XXX umask is one of those stateful things that we should
2911         * reset between each test.
2912         *)
2913    "set file mode creation mask (umask)",
2914    "\
2915 This function sets the mask used for creating new files and
2916 device nodes to C<mask & 0777>.
2917
2918 Typical umask values would be C<022> which creates new files
2919 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
2920 C<002> which creates new files with permissions like
2921 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
2922
2923 The default umask is C<022>.  This is important because it
2924 means that directories and device nodes will be created with
2925 C<0644> or C<0755> mode even if you specify C<0777>.
2926
2927 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
2928
2929 This call returns the previous umask.");
2930
2931   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
2932    [],
2933    "read directories entries",
2934    "\
2935 This returns the list of directory entries in directory C<dir>.
2936
2937 All entries in the directory are returned, including C<.> and
2938 C<..>.  The entries are I<not> sorted, but returned in the same
2939 order as the underlying filesystem.
2940
2941 Also this call returns basic file type information about each
2942 file.  The C<ftyp> field will contain one of the following characters:
2943
2944 =over 4
2945
2946 =item 'b'
2947
2948 Block special
2949
2950 =item 'c'
2951
2952 Char special
2953
2954 =item 'd'
2955
2956 Directory
2957
2958 =item 'f'
2959
2960 FIFO (named pipe)
2961
2962 =item 'l'
2963
2964 Symbolic link
2965
2966 =item 'r'
2967
2968 Regular file
2969
2970 =item 's'
2971
2972 Socket
2973
2974 =item 'u'
2975
2976 Unknown file type
2977
2978 =item '?'
2979
2980 The L<readdir(3)> returned a C<d_type> field with an
2981 unexpected value
2982
2983 =back
2984
2985 This function is primarily intended for use by programs.  To
2986 get a simple list of names, use C<guestfs_ls>.  To get a printable
2987 directory for human consumption, use C<guestfs_ll>.");
2988
2989   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
2990    [],
2991    "create partitions on a block device",
2992    "\
2993 This is a simplified interface to the C<guestfs_sfdisk>
2994 command, where partition sizes are specified in megabytes
2995 only (rounded to the nearest cylinder) and you don't need
2996 to specify the cyls, heads and sectors parameters which
2997 were rarely if ever used anyway.
2998
2999 See also C<guestfs_sfdisk> and the L<sfdisk(8)> manpage.");
3000
3001   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3002    [],
3003    "determine file type inside a compressed file",
3004    "\
3005 This command runs C<file> after first decompressing C<path>
3006 using C<method>.
3007
3008 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3009
3010 Since 1.0.63, use C<guestfs_file> instead which can now
3011 process compressed files.");
3012
3013   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [],
3014    [],
3015    "list extended attributes of a file or directory",
3016    "\
3017 This call lists the extended attributes of the file or directory
3018 C<path>.
3019
3020 At the system call level, this is a combination of the
3021 L<listxattr(2)> and L<getxattr(2)> calls.
3022
3023 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3024
3025   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [],
3026    [],
3027    "list extended attributes of a file or directory",
3028    "\
3029 This is the same as C<guestfs_getxattrs>, but if C<path>
3030 is a symbolic link, then it returns the extended attributes
3031 of the link itself.");
3032
3033   ("setxattr", (RErr, [String "xattr";
3034                        String "val"; Int "vallen"; (* will be BufferIn *)
3035                        Pathname "path"]), 143, [],
3036    [],
3037    "set extended attribute of a file or directory",
3038    "\
3039 This call sets the extended attribute named C<xattr>
3040 of the file C<path> to the value C<val> (of length C<vallen>).
3041 The value is arbitrary 8 bit data.
3042
3043 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3044
3045   ("lsetxattr", (RErr, [String "xattr";
3046                         String "val"; Int "vallen"; (* will be BufferIn *)
3047                         Pathname "path"]), 144, [],
3048    [],
3049    "set extended attribute of a file or directory",
3050    "\
3051 This is the same as C<guestfs_setxattr>, but if C<path>
3052 is a symbolic link, then it sets an extended attribute
3053 of the link itself.");
3054
3055   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [],
3056    [],
3057    "remove extended attribute of a file or directory",
3058    "\
3059 This call removes the extended attribute named C<xattr>
3060 of the file C<path>.
3061
3062 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3063
3064   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [],
3065    [],
3066    "remove extended attribute of a file or directory",
3067    "\
3068 This is the same as C<guestfs_removexattr>, but if C<path>
3069 is a symbolic link, then it removes an extended attribute
3070 of the link itself.");
3071
3072   ("mountpoints", (RHashtable "mps", []), 147, [],
3073    [],
3074    "show mountpoints",
3075    "\
3076 This call is similar to C<guestfs_mounts>.  That call returns
3077 a list of devices.  This one returns a hash table (map) of
3078 device name to directory where the device is mounted.");
3079
3080   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3081   (* This is a special case: while you would expect a parameter
3082    * of type "Pathname", that doesn't work, because it implies
3083    * NEED_ROOT in the generated calling code in stubs.c, and
3084    * this function cannot use NEED_ROOT.
3085    *)
3086    [],
3087    "create a mountpoint",
3088    "\
3089 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3090 specialized calls that can be used to create extra mountpoints
3091 before mounting the first filesystem.
3092
3093 These calls are I<only> necessary in some very limited circumstances,
3094 mainly the case where you want to mount a mix of unrelated and/or
3095 read-only filesystems together.
3096
3097 For example, live CDs often contain a \"Russian doll\" nest of
3098 filesystems, an ISO outer layer, with a squashfs image inside, with
3099 an ext2/3 image inside that.  You can unpack this as follows
3100 in guestfish:
3101
3102  add-ro Fedora-11-i686-Live.iso
3103  run
3104  mkmountpoint /cd
3105  mkmountpoint /squash
3106  mkmountpoint /ext3
3107  mount /dev/sda /cd
3108  mount-loop /cd/LiveOS/squashfs.img /squash
3109  mount-loop /squash/LiveOS/ext3fs.img /ext3
3110
3111 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3112
3113   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3114    [],
3115    "remove a mountpoint",
3116    "\
3117 This calls removes a mountpoint that was previously created
3118 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3119 for full details.");
3120
3121   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3122    [InitISOFS, Always, TestOutputBuffer (
3123       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3124    "read a file",
3125    "\
3126 This calls returns the contents of the file C<path> as a
3127 buffer.
3128
3129 Unlike C<guestfs_cat>, this function can correctly
3130 handle files that contain embedded ASCII NUL characters.
3131 However unlike C<guestfs_download>, this function is limited
3132 in the total size of file that can be handled.");
3133
3134   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3135    [InitISOFS, Always, TestOutputList (
3136       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3137     InitISOFS, Always, TestOutputList (
3138       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3139    "return lines matching a pattern",
3140    "\
3141 This calls the external C<grep> program and returns the
3142 matching lines.");
3143
3144   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3145    [InitISOFS, Always, TestOutputList (
3146       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3147    "return lines matching a pattern",
3148    "\
3149 This calls the external C<egrep> program and returns the
3150 matching lines.");
3151
3152   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3153    [InitISOFS, Always, TestOutputList (
3154       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3155    "return lines matching a pattern",
3156    "\
3157 This calls the external C<fgrep> program and returns the
3158 matching lines.");
3159
3160   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3161    [InitISOFS, Always, TestOutputList (
3162       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3163    "return lines matching a pattern",
3164    "\
3165 This calls the external C<grep -i> program and returns the
3166 matching lines.");
3167
3168   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3169    [InitISOFS, Always, TestOutputList (
3170       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3171    "return lines matching a pattern",
3172    "\
3173 This calls the external C<egrep -i> program and returns the
3174 matching lines.");
3175
3176   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3177    [InitISOFS, Always, TestOutputList (
3178       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3179    "return lines matching a pattern",
3180    "\
3181 This calls the external C<fgrep -i> program and returns the
3182 matching lines.");
3183
3184   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3185    [InitISOFS, Always, TestOutputList (
3186       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3187    "return lines matching a pattern",
3188    "\
3189 This calls the external C<zgrep> program and returns the
3190 matching lines.");
3191
3192   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3193    [InitISOFS, Always, TestOutputList (
3194       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3195    "return lines matching a pattern",
3196    "\
3197 This calls the external C<zegrep> program and returns the
3198 matching lines.");
3199
3200   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3201    [InitISOFS, Always, TestOutputList (
3202       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3203    "return lines matching a pattern",
3204    "\
3205 This calls the external C<zfgrep> program and returns the
3206 matching lines.");
3207
3208   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3209    [InitISOFS, Always, TestOutputList (
3210       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3211    "return lines matching a pattern",
3212    "\
3213 This calls the external C<zgrep -i> program and returns the
3214 matching lines.");
3215
3216   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3217    [InitISOFS, Always, TestOutputList (
3218       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3219    "return lines matching a pattern",
3220    "\
3221 This calls the external C<zegrep -i> program and returns the
3222 matching lines.");
3223
3224   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3225    [InitISOFS, Always, TestOutputList (
3226       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3227    "return lines matching a pattern",
3228    "\
3229 This calls the external C<zfgrep -i> program and returns the
3230 matching lines.");
3231
3232   ("realpath", (RString "rpath", [Pathname "path"]), 163, [],
3233    [InitISOFS, Always, TestOutput (
3234       [["realpath"; "/../directory"]], "/directory")],
3235    "canonicalized absolute pathname",
3236    "\
3237 Return the canonicalized absolute pathname of C<path>.  The
3238 returned path has no C<.>, C<..> or symbolic link path elements.");
3239
3240   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3241    [InitBasicFS, Always, TestOutputStruct (
3242       [["touch"; "/a"];
3243        ["ln"; "/a"; "/b"];
3244        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3245    "create a hard link",
3246    "\
3247 This command creates a hard link using the C<ln> command.");
3248
3249   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3250    [InitBasicFS, Always, TestOutputStruct (
3251       [["touch"; "/a"];
3252        ["touch"; "/b"];
3253        ["ln_f"; "/a"; "/b"];
3254        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3255    "create a hard link",
3256    "\
3257 This command creates a hard link using the C<ln -f> command.
3258 The C<-f> option removes the link (C<linkname>) if it exists already.");
3259
3260   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3261    [InitBasicFS, Always, TestOutputStruct (
3262       [["touch"; "/a"];
3263        ["ln_s"; "a"; "/b"];
3264        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3265    "create a symbolic link",
3266    "\
3267 This command creates a symbolic link using the C<ln -s> command.");
3268
3269   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3270    [InitBasicFS, Always, TestOutput (
3271       [["mkdir_p"; "/a/b"];
3272        ["touch"; "/a/b/c"];
3273        ["ln_sf"; "../d"; "/a/b/c"];
3274        ["readlink"; "/a/b/c"]], "../d")],
3275    "create a symbolic link",
3276    "\
3277 This command creates a symbolic link using the C<ln -sf> command,
3278 The C<-f> option removes the link (C<linkname>) if it exists already.");
3279
3280   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3281    [] (* XXX tested above *),
3282    "read the target of a symbolic link",
3283    "\
3284 This command reads the target of a symbolic link.");
3285
3286   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3287    [InitBasicFS, Always, TestOutputStruct (
3288       [["fallocate"; "/a"; "1000000"];
3289        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3290    "preallocate a file in the guest filesystem",
3291    "\
3292 This command preallocates a file (containing zero bytes) named
3293 C<path> of size C<len> bytes.  If the file exists already, it
3294 is overwritten.
3295
3296 Do not confuse this with the guestfish-specific
3297 C<alloc> command which allocates a file in the host and
3298 attaches it as a device.");
3299
3300   ("swapon_device", (RErr, [Device "device"]), 170, [],
3301    [InitPartition, Always, TestRun (
3302       [["mkswap"; "/dev/sda1"];
3303        ["swapon_device"; "/dev/sda1"];
3304        ["swapoff_device"; "/dev/sda1"]])],
3305    "enable swap on device",
3306    "\
3307 This command enables the libguestfs appliance to use the
3308 swap device or partition named C<device>.  The increased
3309 memory is made available for all commands, for example
3310 those run using C<guestfs_command> or C<guestfs_sh>.
3311
3312 Note that you should not swap to existing guest swap
3313 partitions unless you know what you are doing.  They may
3314 contain hibernation information, or other information that
3315 the guest doesn't want you to trash.  You also risk leaking
3316 information about the host to the guest this way.  Instead,
3317 attach a new host device to the guest and swap on that.");
3318
3319   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3320    [], (* XXX tested by swapon_device *)
3321    "disable swap on device",
3322    "\
3323 This command disables the libguestfs appliance swap
3324 device or partition named C<device>.
3325 See C<guestfs_swapon_device>.");
3326
3327   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3328    [InitBasicFS, Always, TestRun (
3329       [["fallocate"; "/swap"; "8388608"];
3330        ["mkswap_file"; "/swap"];
3331        ["swapon_file"; "/swap"];
3332        ["swapoff_file"; "/swap"]])],
3333    "enable swap on file",
3334    "\
3335 This command enables swap to a file.
3336 See C<guestfs_swapon_device> for other notes.");
3337
3338   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3339    [], (* XXX tested by swapon_file *)
3340    "disable swap on file",
3341    "\
3342 This command disables the libguestfs appliance swap on file.");
3343
3344   ("swapon_label", (RErr, [String "label"]), 174, [],
3345    [InitEmpty, Always, TestRun (
3346       [["sfdiskM"; "/dev/sdb"; ","];
3347        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3348        ["swapon_label"; "swapit"];
3349        ["swapoff_label"; "swapit"];
3350        ["zero"; "/dev/sdb"];
3351        ["blockdev_rereadpt"; "/dev/sdb"]])],
3352    "enable swap on labeled swap partition",
3353    "\
3354 This command enables swap to a labeled swap partition.
3355 See C<guestfs_swapon_device> for other notes.");
3356
3357   ("swapoff_label", (RErr, [String "label"]), 175, [],
3358    [], (* XXX tested by swapon_label *)
3359    "disable swap on labeled swap partition",
3360    "\
3361 This command disables the libguestfs appliance swap on
3362 labeled swap partition.");
3363
3364   ("swapon_uuid", (RErr, [String "uuid"]), 176, [],
3365    (let uuid = uuidgen () in
3366     [InitEmpty, Always, TestRun (
3367        [["mkswap_U"; uuid; "/dev/sdb"];
3368         ["swapon_uuid"; uuid];
3369         ["swapoff_uuid"; uuid]])]),
3370    "enable swap on swap partition by UUID",
3371    "\
3372 This command enables swap to a swap partition with the given UUID.
3373 See C<guestfs_swapon_device> for other notes.");
3374
3375   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [],
3376    [], (* XXX tested by swapon_uuid *)
3377    "disable swap on swap partition by UUID",
3378    "\
3379 This command disables the libguestfs appliance swap partition
3380 with the given UUID.");
3381
3382   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3383    [InitBasicFS, Always, TestRun (
3384       [["fallocate"; "/swap"; "8388608"];
3385        ["mkswap_file"; "/swap"]])],
3386    "create a swap file",
3387    "\
3388 Create a swap file.
3389
3390 This command just writes a swap file signature to an existing
3391 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3392
3393   ("inotify_init", (RErr, [Int "maxevents"]), 179, [],
3394    [InitISOFS, Always, TestRun (
3395       [["inotify_init"; "0"]])],
3396    "create an inotify handle",
3397    "\
3398 This command creates a new inotify handle.
3399 The inotify subsystem can be used to notify events which happen to
3400 objects in the guest filesystem.
3401
3402 C<maxevents> is the maximum number of events which will be
3403 queued up between calls to C<guestfs_inotify_read> or
3404 C<guestfs_inotify_files>.
3405 If this is passed as C<0>, then the kernel (or previously set)
3406 default is used.  For Linux 2.6.29 the default was 16384 events.
3407 Beyond this limit, the kernel throws away events, but records
3408 the fact that it threw them away by setting a flag
3409 C<IN_Q_OVERFLOW> in the returned structure list (see
3410 C<guestfs_inotify_read>).
3411
3412 Before any events are generated, you have to add some
3413 watches to the internal watch list.  See:
3414 C<guestfs_inotify_add_watch>,
3415 C<guestfs_inotify_rm_watch> and
3416 C<guestfs_inotify_watch_all>.
3417
3418 Queued up events should be read periodically by calling
3419 C<guestfs_inotify_read>
3420 (or C<guestfs_inotify_files> which is just a helpful
3421 wrapper around C<guestfs_inotify_read>).  If you don't
3422 read the events out often enough then you risk the internal
3423 queue overflowing.
3424
3425 The handle should be closed after use by calling
3426 C<guestfs_inotify_close>.  This also removes any
3427 watches automatically.
3428
3429 See also L<inotify(7)> for an overview of the inotify interface
3430 as exposed by the Linux kernel, which is roughly what we expose
3431 via libguestfs.  Note that there is one global inotify handle
3432 per libguestfs instance.");
3433
3434   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [],
3435    [InitBasicFS, Always, TestOutputList (
3436       [["inotify_init"; "0"];
3437        ["inotify_add_watch"; "/"; "1073741823"];
3438        ["touch"; "/a"];
3439        ["touch"; "/b"];
3440        ["inotify_files"]], ["a"; "b"])],
3441    "add an inotify watch",
3442    "\
3443 Watch C<path> for the events listed in C<mask>.
3444
3445 Note that if C<path> is a directory then events within that
3446 directory are watched, but this does I<not> happen recursively
3447 (in subdirectories).
3448
3449 Note for non-C or non-Linux callers: the inotify events are
3450 defined by the Linux kernel ABI and are listed in
3451 C</usr/include/sys/inotify.h>.");
3452
3453   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [],
3454    [],
3455    "remove an inotify watch",
3456    "\
3457 Remove a previously defined inotify watch.
3458 See C<guestfs_inotify_add_watch>.");
3459
3460   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [],
3461    [],
3462    "return list of inotify events",
3463    "\
3464 Return the complete queue of events that have happened
3465 since the previous read call.
3466
3467 If no events have happened, this returns an empty list.
3468
3469 I<Note>: In order to make sure that all events have been
3470 read, you must call this function repeatedly until it
3471 returns an empty list.  The reason is that the call will
3472 read events up to the maximum appliance-to-host message
3473 size and leave remaining events in the queue.");
3474
3475   ("inotify_files", (RStringList "paths", []), 183, [],
3476    [],
3477    "return list of watched files that had events",
3478    "\
3479 This function is a helpful wrapper around C<guestfs_inotify_read>
3480 which just returns a list of pathnames of objects that were
3481 touched.  The returned pathnames are sorted and deduplicated.");
3482
3483   ("inotify_close", (RErr, []), 184, [],
3484    [],
3485    "close the inotify handle",
3486    "\
3487 This closes the inotify handle which was previously
3488 opened by inotify_init.  It removes all watches, throws
3489 away any pending events, and deallocates all resources.");
3490
3491   ("setcon", (RErr, [String "context"]), 185, [],
3492    [],
3493    "set SELinux security context",
3494    "\
3495 This sets the SELinux security context of the daemon
3496 to the string C<context>.
3497
3498 See the documentation about SELINUX in L<guestfs(3)>.");
3499
3500   ("getcon", (RString "context", []), 186, [],
3501    [],
3502    "get SELinux security context",
3503    "\
3504 This gets the SELinux security context of the daemon.
3505
3506 See the documentation about SELINUX in L<guestfs(3)>,
3507 and C<guestfs_setcon>");
3508
3509   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3510    [InitEmpty, Always, TestOutput (
3511       [["sfdiskM"; "/dev/sda"; ","];
3512        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3513        ["mount"; "/dev/sda1"; "/"];
3514        ["write_file"; "/new"; "new file contents"; "0"];
3515        ["cat"; "/new"]], "new file contents")],
3516    "make a filesystem with block size",
3517    "\
3518 This call is similar to C<guestfs_mkfs>, but it allows you to
3519 control the block size of the resulting filesystem.  Supported
3520 block sizes depend on the filesystem type, but typically they
3521 are C<1024>, C<2048> or C<4096> only.");
3522
3523   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3524    [InitEmpty, Always, TestOutput (
3525       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3526        ["mke2journal"; "4096"; "/dev/sda1"];
3527        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3528        ["mount"; "/dev/sda2"; "/"];
3529        ["write_file"; "/new"; "new file contents"; "0"];
3530        ["cat"; "/new"]], "new file contents")],
3531    "make ext2/3/4 external journal",
3532    "\
3533 This creates an ext2 external journal on C<device>.  It is equivalent
3534 to the command:
3535
3536  mke2fs -O journal_dev -b blocksize device");
3537
3538   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3539    [InitEmpty, Always, TestOutput (
3540       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3541        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3542        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3543        ["mount"; "/dev/sda2"; "/"];
3544        ["write_file"; "/new"; "new file contents"; "0"];
3545        ["cat"; "/new"]], "new file contents")],
3546    "make ext2/3/4 external journal with label",
3547    "\
3548 This creates an ext2 external journal on C<device> with label C<label>.");
3549
3550   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [],
3551    (let uuid = uuidgen () in
3552     [InitEmpty, Always, TestOutput (
3553        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3554         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3555         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3556         ["mount"; "/dev/sda2"; "/"];
3557         ["write_file"; "/new"; "new file contents"; "0"];
3558         ["cat"; "/new"]], "new file contents")]),
3559    "make ext2/3/4 external journal with UUID",
3560    "\
3561 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3562
3563   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3564    [],
3565    "make ext2/3/4 filesystem with external journal",
3566    "\
3567 This creates an ext2/3/4 filesystem on C<device> with
3568 an external journal on C<journal>.  It is equivalent
3569 to the command:
3570
3571  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3572
3573 See also C<guestfs_mke2journal>.");
3574
3575   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3576    [],
3577    "make ext2/3/4 filesystem with external journal",
3578    "\
3579 This creates an ext2/3/4 filesystem on C<device> with
3580 an external journal on the journal labeled C<label>.
3581
3582 See also C<guestfs_mke2journal_L>.");
3583
3584   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [],
3585    [],
3586    "make ext2/3/4 filesystem with external journal",
3587    "\
3588 This creates an ext2/3/4 filesystem on C<device> with
3589 an external journal on the journal with UUID C<uuid>.
3590
3591 See also C<guestfs_mke2journal_U>.");
3592
3593   ("modprobe", (RErr, [String "modulename"]), 194, [],
3594    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3595    "load a kernel module",
3596    "\
3597 This loads a kernel module in the appliance.
3598
3599 The kernel module must have been whitelisted when libguestfs
3600 was built (see C<appliance/kmod.whitelist.in> in the source).");
3601
3602   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3603    [InitNone, Always, TestOutput (
3604      [["echo_daemon"; "This is a test"]], "This is a test"
3605    )],
3606    "echo arguments back to the client",
3607    "\
3608 This command concatenate the list of C<words> passed with single spaces between
3609 them and returns the resulting string.
3610
3611 You can use this command to test the connection through to the daemon.
3612
3613 See also C<guestfs_ping_daemon>.");
3614
3615   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3616    [], (* There is a regression test for this. *)
3617    "find all files and directories, returning NUL-separated list",
3618    "\
3619 This command lists out all files and directories, recursively,
3620 starting at C<directory>, placing the resulting list in the
3621 external file called C<files>.
3622
3623 This command works the same way as C<guestfs_find> with the
3624 following exceptions:
3625
3626 =over 4
3627
3628 =item *
3629
3630 The resulting list is written to an external file.
3631
3632 =item *
3633
3634 Items (filenames) in the result are separated
3635 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3636
3637 =item *
3638
3639 This command is not limited in the number of names that it
3640 can return.
3641
3642 =item *
3643
3644 The result list is not sorted.
3645
3646 =back");
3647
3648 ]
3649
3650 let all_functions = non_daemon_functions @ daemon_functions
3651
3652 (* In some places we want the functions to be displayed sorted
3653  * alphabetically, so this is useful:
3654  *)
3655 let all_functions_sorted =
3656   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
3657                compare n1 n2) all_functions
3658
3659 (* Field types for structures. *)
3660 type field =
3661   | FChar                       (* C 'char' (really, a 7 bit byte). *)
3662   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
3663   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
3664   | FUInt32
3665   | FInt32
3666   | FUInt64
3667   | FInt64
3668   | FBytes                      (* Any int measure that counts bytes. *)
3669   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
3670   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
3671
3672 (* Because we generate extra parsing code for LVM command line tools,
3673  * we have to pull out the LVM columns separately here.
3674  *)
3675 let lvm_pv_cols = [
3676   "pv_name", FString;
3677   "pv_uuid", FUUID;
3678   "pv_fmt", FString;
3679   "pv_size", FBytes;
3680   "dev_size", FBytes;
3681   "pv_free", FBytes;
3682   "pv_used", FBytes;
3683   "pv_attr", FString (* XXX *);
3684   "pv_pe_count", FInt64;
3685   "pv_pe_alloc_count", FInt64;
3686   "pv_tags", FString;
3687   "pe_start", FBytes;
3688   "pv_mda_count", FInt64;
3689   "pv_mda_free", FBytes;
3690   (* Not in Fedora 10:
3691      "pv_mda_size", FBytes;
3692   *)
3693 ]
3694 let lvm_vg_cols = [
3695   "vg_name", FString;
3696   "vg_uuid", FUUID;
3697   "vg_fmt", FString;
3698   "vg_attr", FString (* XXX *);
3699   "vg_size", FBytes;
3700   "vg_free", FBytes;
3701   "vg_sysid", FString;
3702   "vg_extent_size", FBytes;
3703   "vg_extent_count", FInt64;
3704   "vg_free_count", FInt64;
3705   "max_lv", FInt64;
3706   "max_pv", FInt64;
3707   "pv_count", FInt64;
3708   "lv_count", FInt64;
3709   "snap_count", FInt64;
3710   "vg_seqno", FInt64;
3711   "vg_tags", FString;
3712   "vg_mda_count", FInt64;
3713   "vg_mda_free", FBytes;
3714   (* Not in Fedora 10:
3715      "vg_mda_size", FBytes;
3716   *)
3717 ]
3718 let lvm_lv_cols = [
3719   "lv_name", FString;
3720   "lv_uuid", FUUID;
3721   "lv_attr", FString (* XXX *);
3722   "lv_major", FInt64;
3723   "lv_minor", FInt64;
3724   "lv_kernel_major", FInt64;
3725   "lv_kernel_minor", FInt64;
3726   "lv_size", FBytes;
3727   "seg_count", FInt64;
3728   "origin", FString;
3729   "snap_percent", FOptPercent;
3730   "copy_percent", FOptPercent;
3731   "move_pv", FString;
3732   "lv_tags", FString;
3733   "mirror_log", FString;
3734   "modules", FString;
3735 ]
3736
3737 (* Names and fields in all structures (in RStruct and RStructList)
3738  * that we support.
3739  *)
3740 let structs = [
3741   (* The old RIntBool return type, only ever used for aug_defnode.  Do
3742    * not use this struct in any new code.
3743    *)
3744   "int_bool", [
3745     "i", FInt32;                (* for historical compatibility *)
3746     "b", FInt32;                (* for historical compatibility *)
3747   ];
3748
3749   (* LVM PVs, VGs, LVs. *)
3750   "lvm_pv", lvm_pv_cols;
3751   "lvm_vg", lvm_vg_cols;
3752   "lvm_lv", lvm_lv_cols;
3753
3754   (* Column names and types from stat structures.
3755    * NB. Can't use things like 'st_atime' because glibc header files
3756    * define some of these as macros.  Ugh.
3757    *)
3758   "stat", [
3759     "dev", FInt64;
3760     "ino", FInt64;
3761     "mode", FInt64;
3762     "nlink", FInt64;
3763     "uid", FInt64;
3764     "gid", FInt64;
3765     "rdev", FInt64;
3766     "size", FInt64;
3767     "blksize", FInt64;
3768     "blocks", FInt64;
3769     "atime", FInt64;
3770     "mtime", FInt64;
3771     "ctime", FInt64;
3772   ];
3773   "statvfs", [
3774     "bsize", FInt64;
3775     "frsize", FInt64;
3776     "blocks", FInt64;
3777     "bfree", FInt64;
3778     "bavail", FInt64;
3779     "files", FInt64;
3780     "ffree", FInt64;
3781     "favail", FInt64;
3782     "fsid", FInt64;
3783     "flag", FInt64;
3784     "namemax", FInt64;
3785   ];
3786
3787   (* Column names in dirent structure. *)
3788   "dirent", [
3789     "ino", FInt64;
3790     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
3791     "ftyp", FChar;
3792     "name", FString;
3793   ];
3794
3795   (* Version numbers. *)
3796   "version", [
3797     "major", FInt64;
3798     "minor", FInt64;
3799     "release", FInt64;
3800     "extra", FString;
3801   ];
3802
3803   (* Extended attribute. *)
3804   "xattr", [
3805     "attrname", FString;
3806     "attrval", FBuffer;
3807   ];
3808
3809   (* Inotify events. *)
3810   "inotify_event", [
3811     "in_wd", FInt64;
3812     "in_mask", FUInt32;
3813     "in_cookie", FUInt32;
3814     "in_name", FString;
3815   ];
3816 ] (* end of structs *)
3817
3818 (* Ugh, Java has to be different ..
3819  * These names are also used by the Haskell bindings.
3820  *)
3821 let java_structs = [
3822   "int_bool", "IntBool";
3823   "lvm_pv", "PV";
3824   "lvm_vg", "VG";
3825   "lvm_lv", "LV";
3826   "stat", "Stat";
3827   "statvfs", "StatVFS";
3828   "dirent", "Dirent";
3829   "version", "Version";
3830   "xattr", "XAttr";
3831   "inotify_event", "INotifyEvent";
3832 ]
3833
3834 (* What structs are actually returned. *)
3835 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
3836
3837 (* Returns a list of RStruct/RStructList structs that are returned
3838  * by any function.  Each element of returned list is a pair:
3839  *
3840  * (structname, RStructOnly)
3841  *    == there exists function which returns RStruct (_, structname)
3842  * (structname, RStructListOnly)
3843  *    == there exists function which returns RStructList (_, structname)
3844  * (structname, RStructAndList)
3845  *    == there are functions returning both RStruct (_, structname)
3846  *                                      and RStructList (_, structname)
3847  *)
3848 let rstructs_used =
3849   (* ||| is a "logical OR" for rstructs_used_t *)
3850   let (|||) a b =
3851     match a, b with
3852     | RStructAndList, _
3853     | _, RStructAndList -> RStructAndList
3854     | RStructOnly, RStructListOnly
3855     | RStructListOnly, RStructOnly -> RStructAndList
3856     | RStructOnly, RStructOnly -> RStructOnly
3857     | RStructListOnly, RStructListOnly -> RStructListOnly
3858   in
3859
3860   let h = Hashtbl.create 13 in
3861
3862   (* if elem->oldv exists, update entry using ||| operator,
3863    * else just add elem->newv to the hash
3864    *)
3865   let update elem newv =
3866     try  let oldv = Hashtbl.find h elem in
3867          Hashtbl.replace h elem (newv ||| oldv)
3868     with Not_found -> Hashtbl.add h elem newv
3869   in
3870
3871   List.iter (
3872     fun (_, style, _, _, _, _, _) ->
3873       match fst style with
3874       | RStruct (_, structname) -> update structname RStructOnly
3875       | RStructList (_, structname) -> update structname RStructListOnly
3876       | _ -> ()
3877   ) all_functions;
3878
3879   (* return key->values as a list of (key,value) *)
3880   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
3881
3882 (* debug:
3883 let () =
3884   List.iter (
3885     function
3886     | sn, RStructOnly -> printf "%s RStructOnly\n" sn
3887     | sn, RStructListOnly -> printf "%s RStructListOnly\n" sn
3888     | sn, RStructAndList -> printf "%s RStructAndList\n" sn
3889   ) rstructs_used
3890 *)
3891
3892 (* Used for testing language bindings. *)
3893 type callt =
3894   | CallString of string
3895   | CallOptString of string option
3896   | CallStringList of string list
3897   | CallInt of int
3898   | CallBool of bool
3899
3900 (* Used to memoize the result of pod2text. *)
3901 let pod2text_memo_filename = "src/.pod2text.data"
3902 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
3903   try
3904     let chan = open_in pod2text_memo_filename in
3905     let v = input_value chan in
3906     close_in chan;
3907     v
3908   with
3909     _ -> Hashtbl.create 13
3910 let pod2text_memo_updated () =
3911   let chan = open_out pod2text_memo_filename in
3912   output_value chan pod2text_memo;
3913   close_out chan
3914
3915 (* Useful functions.
3916  * Note we don't want to use any external OCaml libraries which
3917  * makes this a bit harder than it should be.
3918  *)
3919 let failwithf fs = ksprintf failwith fs
3920
3921 let replace_char s c1 c2 =
3922   let s2 = String.copy s in
3923   let r = ref false in
3924   for i = 0 to String.length s2 - 1 do
3925     if String.unsafe_get s2 i = c1 then (
3926       String.unsafe_set s2 i c2;
3927       r := true
3928     )
3929   done;
3930   if not !r then s else s2
3931
3932 let isspace c =
3933   c = ' '
3934   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
3935
3936 let triml ?(test = isspace) str =
3937   let i = ref 0 in
3938   let n = ref (String.length str) in
3939   while !n > 0 && test str.[!i]; do
3940     decr n;
3941     incr i
3942   done;
3943   if !i = 0 then str
3944   else String.sub str !i !n
3945
3946 let trimr ?(test = isspace) str =
3947   let n = ref (String.length str) in
3948   while !n > 0 && test str.[!n-1]; do
3949     decr n
3950   done;
3951   if !n = String.length str then str
3952   else String.sub str 0 !n
3953
3954 let trim ?(test = isspace) str =
3955   trimr ~test (triml ~test str)
3956
3957 let rec find s sub =
3958   let len = String.length s in
3959   let sublen = String.length sub in
3960   let rec loop i =
3961     if i <= len-sublen then (
3962       let rec loop2 j =
3963         if j < sublen then (
3964           if s.[i+j] = sub.[j] then loop2 (j+1)
3965           else -1
3966         ) else
3967           i (* found *)
3968       in
3969       let r = loop2 0 in
3970       if r = -1 then loop (i+1) else r
3971     ) else
3972       -1 (* not found *)
3973   in
3974   loop 0
3975
3976 let rec replace_str s s1 s2 =
3977   let len = String.length s in
3978   let sublen = String.length s1 in
3979   let i = find s s1 in
3980   if i = -1 then s
3981   else (
3982     let s' = String.sub s 0 i in
3983     let s'' = String.sub s (i+sublen) (len-i-sublen) in
3984     s' ^ s2 ^ replace_str s'' s1 s2
3985   )
3986
3987 let rec string_split sep str =
3988   let len = String.length str in
3989   let seplen = String.length sep in
3990   let i = find str sep in
3991   if i = -1 then [str]
3992   else (
3993     let s' = String.sub str 0 i in
3994     let s'' = String.sub str (i+seplen) (len-i-seplen) in
3995     s' :: string_split sep s''
3996   )
3997
3998 let files_equal n1 n2 =
3999   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4000   match Sys.command cmd with
4001   | 0 -> true
4002   | 1 -> false
4003   | i -> failwithf "%s: failed with error code %d" cmd i
4004
4005 let rec filter_map f = function
4006   | [] -> []
4007   | x :: xs ->
4008       match f x with
4009       | Some y -> y :: filter_map f xs
4010       | None -> filter_map f xs
4011
4012 let rec find_map f = function
4013   | [] -> raise Not_found
4014   | x :: xs ->
4015       match f x with
4016       | Some y -> y
4017       | None -> find_map f xs
4018
4019 let iteri f xs =
4020   let rec loop i = function
4021     | [] -> ()
4022     | x :: xs -> f i x; loop (i+1) xs
4023   in
4024   loop 0 xs
4025
4026 let mapi f xs =
4027   let rec loop i = function
4028     | [] -> []
4029     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4030   in
4031   loop 0 xs
4032
4033 let name_of_argt = function
4034   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4035   | StringList n | DeviceList n | Bool n | Int n
4036   | FileIn n | FileOut n -> n
4037
4038 let java_name_of_struct typ =
4039   try List.assoc typ java_structs
4040   with Not_found ->
4041     failwithf
4042       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4043
4044 let cols_of_struct typ =
4045   try List.assoc typ structs
4046   with Not_found ->
4047     failwithf "cols_of_struct: unknown struct %s" typ
4048
4049 let seq_of_test = function
4050   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4051   | TestOutputListOfDevices (s, _)
4052   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4053   | TestOutputTrue s | TestOutputFalse s
4054   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4055   | TestOutputStruct (s, _)
4056   | TestLastFail s -> s
4057
4058 (* Handling for function flags. *)
4059 let protocol_limit_warning =
4060   "Because of the message protocol, there is a transfer limit
4061 of somewhere between 2MB and 4MB.  To transfer large files you should use
4062 FTP."
4063
4064 let danger_will_robinson =
4065   "B<This command is dangerous.  Without careful use you
4066 can easily destroy all your data>."
4067
4068 let deprecation_notice flags =
4069   try
4070     let alt =
4071       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4072     let txt =
4073       sprintf "This function is deprecated.
4074 In new code, use the C<%s> call instead.
4075
4076 Deprecated functions will not be removed from the API, but the
4077 fact that they are deprecated indicates that there are problems
4078 with correct use of these functions." alt in
4079     Some txt
4080   with
4081     Not_found -> None
4082
4083 (* Check function names etc. for consistency. *)
4084 let check_functions () =
4085   let contains_uppercase str =
4086     let len = String.length str in
4087     let rec loop i =
4088       if i >= len then false
4089       else (
4090         let c = str.[i] in
4091         if c >= 'A' && c <= 'Z' then true
4092         else loop (i+1)
4093       )
4094     in
4095     loop 0
4096   in
4097
4098   (* Check function names. *)
4099   List.iter (
4100     fun (name, _, _, _, _, _, _) ->
4101       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4102         failwithf "function name %s does not need 'guestfs' prefix" name;
4103       if name = "" then
4104         failwithf "function name is empty";
4105       if name.[0] < 'a' || name.[0] > 'z' then
4106         failwithf "function name %s must start with lowercase a-z" name;
4107       if String.contains name '-' then
4108         failwithf "function name %s should not contain '-', use '_' instead."
4109           name
4110   ) all_functions;
4111
4112   (* Check function parameter/return names. *)
4113   List.iter (
4114     fun (name, style, _, _, _, _, _) ->
4115       let check_arg_ret_name n =
4116         if contains_uppercase n then
4117           failwithf "%s param/ret %s should not contain uppercase chars"
4118             name n;
4119         if String.contains n '-' || String.contains n '_' then
4120           failwithf "%s param/ret %s should not contain '-' or '_'"
4121             name n;
4122         if n = "value" then
4123           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;
4124         if n = "int" || n = "char" || n = "short" || n = "long" then
4125           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4126         if n = "i" || n = "n" then
4127           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4128         if n = "argv" || n = "args" then
4129           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4130
4131         (* List Haskell, OCaml and C keywords here.
4132          * http://www.haskell.org/haskellwiki/Keywords
4133          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4134          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4135          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4136          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4137          * Omitting _-containing words, since they're handled above.
4138          * Omitting the OCaml reserved word, "val", is ok,
4139          * and saves us from renaming several parameters.
4140          *)
4141         let reserved = [
4142           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4143           "char"; "class"; "const"; "constraint"; "continue"; "data";
4144           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4145           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4146           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4147           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4148           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4149           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4150           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4151           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4152           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4153           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4154           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4155           "volatile"; "when"; "where"; "while";
4156           ] in
4157         if List.mem n reserved then
4158           failwithf "%s has param/ret using reserved word %s" name n;
4159       in
4160
4161       (match fst style with
4162        | RErr -> ()
4163        | RInt n | RInt64 n | RBool n
4164        | RConstString n | RConstOptString n | RString n
4165        | RStringList n | RStruct (n, _) | RStructList (n, _)
4166        | RHashtable n | RBufferOut n ->
4167            check_arg_ret_name n
4168       );
4169       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4170   ) all_functions;
4171
4172   (* Check short descriptions. *)
4173   List.iter (
4174     fun (name, _, _, _, _, shortdesc, _) ->
4175       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4176         failwithf "short description of %s should begin with lowercase." name;
4177       let c = shortdesc.[String.length shortdesc-1] in
4178       if c = '\n' || c = '.' then
4179         failwithf "short description of %s should not end with . or \\n." name
4180   ) all_functions;
4181
4182   (* Check long dscriptions. *)
4183   List.iter (
4184     fun (name, _, _, _, _, _, longdesc) ->
4185       if longdesc.[String.length longdesc-1] = '\n' then
4186         failwithf "long description of %s should not end with \\n." name
4187   ) all_functions;
4188
4189   (* Check proc_nrs. *)
4190   List.iter (
4191     fun (name, _, proc_nr, _, _, _, _) ->
4192       if proc_nr <= 0 then
4193         failwithf "daemon function %s should have proc_nr > 0" name
4194   ) daemon_functions;
4195
4196   List.iter (
4197     fun (name, _, proc_nr, _, _, _, _) ->
4198       if proc_nr <> -1 then
4199         failwithf "non-daemon function %s should have proc_nr -1" name
4200   ) non_daemon_functions;
4201
4202   let proc_nrs =
4203     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4204       daemon_functions in
4205   let proc_nrs =
4206     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4207   let rec loop = function
4208     | [] -> ()
4209     | [_] -> ()
4210     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4211         loop rest
4212     | (name1,nr1) :: (name2,nr2) :: _ ->
4213         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4214           name1 name2 nr1 nr2
4215   in
4216   loop proc_nrs;
4217
4218   (* Check tests. *)
4219   List.iter (
4220     function
4221       (* Ignore functions that have no tests.  We generate a
4222        * warning when the user does 'make check' instead.
4223        *)
4224     | name, _, _, _, [], _, _ -> ()
4225     | name, _, _, _, tests, _, _ ->
4226         let funcs =
4227           List.map (
4228             fun (_, _, test) ->
4229               match seq_of_test test with
4230               | [] ->
4231                   failwithf "%s has a test containing an empty sequence" name
4232               | cmds -> List.map List.hd cmds
4233           ) tests in
4234         let funcs = List.flatten funcs in
4235
4236         let tested = List.mem name funcs in
4237
4238         if not tested then
4239           failwithf "function %s has tests but does not test itself" name
4240   ) all_functions
4241
4242 (* 'pr' prints to the current output file. *)
4243 let chan = ref stdout
4244 let pr fs = ksprintf (output_string !chan) fs
4245
4246 (* Generate a header block in a number of standard styles. *)
4247 type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
4248 type license = GPLv2 | LGPLv2
4249
4250 let generate_header comment license =
4251   let c = match comment with
4252     | CStyle ->     pr "/* "; " *"
4253     | HashStyle ->  pr "# ";  "#"
4254     | OCamlStyle -> pr "(* "; " *"
4255     | HaskellStyle -> pr "{- "; "  " in
4256   pr "libguestfs generated file\n";
4257   pr "%s WARNING: THIS FILE IS GENERATED BY 'src/generator.ml'.\n" c;
4258   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4259   pr "%s\n" c;
4260   pr "%s Copyright (C) 2009 Red Hat Inc.\n" c;
4261   pr "%s\n" c;
4262   (match license with
4263    | GPLv2 ->
4264        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4265        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4266        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4267        pr "%s (at your option) any later version.\n" c;
4268        pr "%s\n" c;
4269        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4270        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4271        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4272        pr "%s GNU General Public License for more details.\n" c;
4273        pr "%s\n" c;
4274        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4275        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4276        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4277
4278    | LGPLv2 ->
4279        pr "%s This library is free software; you can redistribute it and/or\n" c;
4280        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4281        pr "%s License as published by the Free Software Foundation; either\n" c;
4282        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4283        pr "%s\n" c;
4284        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4285        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4286        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4287        pr "%s Lesser General Public License for more details.\n" c;
4288        pr "%s\n" c;
4289        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4290        pr "%s License along with this library; if not, write to the Free Software\n" c;
4291        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4292   );
4293   (match comment with
4294    | CStyle -> pr " */\n"
4295    | HashStyle -> ()
4296    | OCamlStyle -> pr " *)\n"
4297    | HaskellStyle -> pr "-}\n"
4298   );
4299   pr "\n"
4300
4301 (* Start of main code generation functions below this line. *)
4302
4303 (* Generate the pod documentation for the C API. *)
4304 let rec generate_actions_pod () =
4305   List.iter (
4306     fun (shortname, style, _, flags, _, _, longdesc) ->
4307       if not (List.mem NotInDocs flags) then (
4308         let name = "guestfs_" ^ shortname in
4309         pr "=head2 %s\n\n" name;
4310         pr " ";
4311         generate_prototype ~extern:false ~handle:"handle" name style;
4312         pr "\n\n";
4313         pr "%s\n\n" longdesc;
4314         (match fst style with
4315          | RErr ->
4316              pr "This function returns 0 on success or -1 on error.\n\n"
4317          | RInt _ ->
4318              pr "On error this function returns -1.\n\n"
4319          | RInt64 _ ->
4320              pr "On error this function returns -1.\n\n"
4321          | RBool _ ->
4322              pr "This function returns a C truth value on success or -1 on error.\n\n"
4323          | RConstString _ ->
4324              pr "This function returns a string, or NULL on error.
4325 The string is owned by the guest handle and must I<not> be freed.\n\n"
4326          | RConstOptString _ ->
4327              pr "This function returns a string which may be NULL.
4328 There is way to return an error from this function.
4329 The string is owned by the guest handle and must I<not> be freed.\n\n"
4330          | RString _ ->
4331              pr "This function returns a string, or NULL on error.
4332 I<The caller must free the returned string after use>.\n\n"
4333          | RStringList _ ->
4334              pr "This function returns a NULL-terminated array of strings
4335 (like L<environ(3)>), or NULL if there was an error.
4336 I<The caller must free the strings and the array after use>.\n\n"
4337          | RStruct (_, typ) ->
4338              pr "This function returns a C<struct guestfs_%s *>,
4339 or NULL if there was an error.
4340 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
4341          | RStructList (_, typ) ->
4342              pr "This function returns a C<struct guestfs_%s_list *>
4343 (see E<lt>guestfs-structs.hE<gt>),
4344 or NULL if there was an error.
4345 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
4346          | RHashtable _ ->
4347              pr "This function returns a NULL-terminated array of
4348 strings, or NULL if there was an error.
4349 The array of strings will always have length C<2n+1>, where
4350 C<n> keys and values alternate, followed by the trailing NULL entry.
4351 I<The caller must free the strings and the array after use>.\n\n"
4352          | RBufferOut _ ->
4353              pr "This function returns a buffer, or NULL on error.
4354 The size of the returned buffer is written to C<*size_r>.
4355 I<The caller must free the returned buffer after use>.\n\n"
4356         );
4357         if List.mem ProtocolLimitWarning flags then
4358           pr "%s\n\n" protocol_limit_warning;
4359         if List.mem DangerWillRobinson flags then
4360           pr "%s\n\n" danger_will_robinson;
4361         match deprecation_notice flags with
4362         | None -> ()
4363         | Some txt -> pr "%s\n\n" txt
4364       )
4365   ) all_functions_sorted
4366
4367 and generate_structs_pod () =
4368   (* Structs documentation. *)
4369   List.iter (
4370     fun (typ, cols) ->
4371       pr "=head2 guestfs_%s\n" typ;
4372       pr "\n";
4373       pr " struct guestfs_%s {\n" typ;
4374       List.iter (
4375         function
4376         | name, FChar -> pr "   char %s;\n" name
4377         | name, FUInt32 -> pr "   uint32_t %s;\n" name
4378         | name, FInt32 -> pr "   int32_t %s;\n" name
4379         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
4380         | name, FInt64 -> pr "   int64_t %s;\n" name
4381         | name, FString -> pr "   char *%s;\n" name
4382         | name, FBuffer ->
4383             pr "   /* The next two fields describe a byte array. */\n";
4384             pr "   uint32_t %s_len;\n" name;
4385             pr "   char *%s;\n" name
4386         | name, FUUID ->
4387             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
4388             pr "   char %s[32];\n" name
4389         | name, FOptPercent ->
4390             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
4391             pr "   float %s;\n" name
4392       ) cols;
4393       pr " };\n";
4394       pr " \n";
4395       pr " struct guestfs_%s_list {\n" typ;
4396       pr "   uint32_t len; /* Number of elements in list. */\n";
4397       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
4398       pr " };\n";
4399       pr " \n";
4400       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
4401       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
4402         typ typ;
4403       pr "\n"
4404   ) structs
4405
4406 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
4407  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
4408  *
4409  * We have to use an underscore instead of a dash because otherwise
4410  * rpcgen generates incorrect code.
4411  *
4412  * This header is NOT exported to clients, but see also generate_structs_h.
4413  *)
4414 and generate_xdr () =
4415   generate_header CStyle LGPLv2;
4416
4417   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
4418   pr "typedef string str<>;\n";
4419   pr "\n";
4420
4421   (* Internal structures. *)
4422   List.iter (
4423     function
4424     | typ, cols ->
4425         pr "struct guestfs_int_%s {\n" typ;
4426         List.iter (function
4427                    | name, FChar -> pr "  char %s;\n" name
4428                    | name, FString -> pr "  string %s<>;\n" name
4429                    | name, FBuffer -> pr "  opaque %s<>;\n" name
4430                    | name, FUUID -> pr "  opaque %s[32];\n" name
4431                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
4432                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
4433                    | name, FOptPercent -> pr "  float %s;\n" name
4434                   ) cols;
4435         pr "};\n";
4436         pr "\n";
4437         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
4438         pr "\n";
4439   ) structs;
4440
4441   List.iter (
4442     fun (shortname, style, _, _, _, _, _) ->
4443       let name = "guestfs_" ^ shortname in
4444
4445       (match snd style with
4446        | [] -> ()
4447        | args ->
4448            pr "struct %s_args {\n" name;
4449            List.iter (
4450              function
4451              | Pathname n | Device n | Dev_or_Path n | String n -> pr "  string %s<>;\n" n
4452              | OptString n -> pr "  str *%s;\n" n
4453              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
4454              | Bool n -> pr "  bool %s;\n" n
4455              | Int n -> pr "  int %s;\n" n
4456              | FileIn _ | FileOut _ -> ()
4457            ) args;
4458            pr "};\n\n"
4459       );
4460       (match fst style with
4461        | RErr -> ()
4462        | RInt n ->
4463            pr "struct %s_ret {\n" name;
4464            pr "  int %s;\n" n;
4465            pr "};\n\n"
4466        | RInt64 n ->
4467            pr "struct %s_ret {\n" name;
4468            pr "  hyper %s;\n" n;
4469            pr "};\n\n"
4470        | RBool n ->
4471            pr "struct %s_ret {\n" name;
4472            pr "  bool %s;\n" n;
4473            pr "};\n\n"
4474        | RConstString _ | RConstOptString _ ->
4475            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4476        | RString n ->
4477            pr "struct %s_ret {\n" name;
4478            pr "  string %s<>;\n" n;
4479            pr "};\n\n"
4480        | RStringList n ->
4481            pr "struct %s_ret {\n" name;
4482            pr "  str %s<>;\n" n;
4483            pr "};\n\n"
4484        | RStruct (n, typ) ->
4485            pr "struct %s_ret {\n" name;
4486            pr "  guestfs_int_%s %s;\n" typ n;
4487            pr "};\n\n"
4488        | RStructList (n, typ) ->
4489            pr "struct %s_ret {\n" name;
4490            pr "  guestfs_int_%s_list %s;\n" typ n;
4491            pr "};\n\n"
4492        | RHashtable n ->
4493            pr "struct %s_ret {\n" name;
4494            pr "  str %s<>;\n" n;
4495            pr "};\n\n"
4496        | RBufferOut n ->
4497            pr "struct %s_ret {\n" name;
4498            pr "  opaque %s<>;\n" n;
4499            pr "};\n\n"
4500       );
4501   ) daemon_functions;
4502
4503   (* Table of procedure numbers. *)
4504   pr "enum guestfs_procedure {\n";
4505   List.iter (
4506     fun (shortname, _, proc_nr, _, _, _, _) ->
4507       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
4508   ) daemon_functions;
4509   pr "  GUESTFS_PROC_NR_PROCS\n";
4510   pr "};\n";
4511   pr "\n";
4512
4513   (* Having to choose a maximum message size is annoying for several
4514    * reasons (it limits what we can do in the API), but it (a) makes
4515    * the protocol a lot simpler, and (b) provides a bound on the size
4516    * of the daemon which operates in limited memory space.  For large
4517    * file transfers you should use FTP.
4518    *)
4519   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
4520   pr "\n";
4521
4522   (* Message header, etc. *)
4523   pr "\
4524 /* The communication protocol is now documented in the guestfs(3)
4525  * manpage.
4526  */
4527
4528 const GUESTFS_PROGRAM = 0x2000F5F5;
4529 const GUESTFS_PROTOCOL_VERSION = 1;
4530
4531 /* These constants must be larger than any possible message length. */
4532 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
4533 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
4534
4535 enum guestfs_message_direction {
4536   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
4537   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
4538 };
4539
4540 enum guestfs_message_status {
4541   GUESTFS_STATUS_OK = 0,
4542   GUESTFS_STATUS_ERROR = 1
4543 };
4544
4545 const GUESTFS_ERROR_LEN = 256;
4546
4547 struct guestfs_message_error {
4548   string error_message<GUESTFS_ERROR_LEN>;
4549 };
4550
4551 struct guestfs_message_header {
4552   unsigned prog;                     /* GUESTFS_PROGRAM */
4553   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
4554   guestfs_procedure proc;            /* GUESTFS_PROC_x */
4555   guestfs_message_direction direction;
4556   unsigned serial;                   /* message serial number */
4557   guestfs_message_status status;
4558 };
4559
4560 const GUESTFS_MAX_CHUNK_SIZE = 8192;
4561
4562 struct guestfs_chunk {
4563   int cancel;                        /* if non-zero, transfer is cancelled */
4564   /* data size is 0 bytes if the transfer has finished successfully */
4565   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
4566 };
4567 "
4568
4569 (* Generate the guestfs-structs.h file. *)
4570 and generate_structs_h () =
4571   generate_header CStyle LGPLv2;
4572
4573   (* This is a public exported header file containing various
4574    * structures.  The structures are carefully written to have
4575    * exactly the same in-memory format as the XDR structures that
4576    * we use on the wire to the daemon.  The reason for creating
4577    * copies of these structures here is just so we don't have to
4578    * export the whole of guestfs_protocol.h (which includes much
4579    * unrelated and XDR-dependent stuff that we don't want to be
4580    * public, or required by clients).
4581    *
4582    * To reiterate, we will pass these structures to and from the
4583    * client with a simple assignment or memcpy, so the format
4584    * must be identical to what rpcgen / the RFC defines.
4585    *)
4586
4587   (* Public structures. *)
4588   List.iter (
4589     fun (typ, cols) ->
4590       pr "struct guestfs_%s {\n" typ;
4591       List.iter (
4592         function
4593         | name, FChar -> pr "  char %s;\n" name
4594         | name, FString -> pr "  char *%s;\n" name
4595         | name, FBuffer ->
4596             pr "  uint32_t %s_len;\n" name;
4597             pr "  char *%s;\n" name
4598         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
4599         | name, FUInt32 -> pr "  uint32_t %s;\n" name
4600         | name, FInt32 -> pr "  int32_t %s;\n" name
4601         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
4602         | name, FInt64 -> pr "  int64_t %s;\n" name
4603         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
4604       ) cols;
4605       pr "};\n";
4606       pr "\n";
4607       pr "struct guestfs_%s_list {\n" typ;
4608       pr "  uint32_t len;\n";
4609       pr "  struct guestfs_%s *val;\n" typ;
4610       pr "};\n";
4611       pr "\n";
4612       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
4613       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
4614       pr "\n"
4615   ) structs
4616
4617 (* Generate the guestfs-actions.h file. *)
4618 and generate_actions_h () =
4619   generate_header CStyle LGPLv2;
4620   List.iter (
4621     fun (shortname, style, _, _, _, _, _) ->
4622       let name = "guestfs_" ^ shortname in
4623       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4624         name style
4625   ) all_functions
4626
4627 (* Generate the guestfs-internal-actions.h file. *)
4628 and generate_internal_actions_h () =
4629   generate_header CStyle LGPLv2;
4630   List.iter (
4631     fun (shortname, style, _, _, _, _, _) ->
4632       let name = "guestfs__" ^ shortname in
4633       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
4634         name style
4635   ) non_daemon_functions
4636
4637 (* Generate the client-side dispatch stubs. *)
4638 and generate_client_actions () =
4639   generate_header CStyle LGPLv2;
4640
4641   pr "\
4642 #include <stdio.h>
4643 #include <stdlib.h>
4644
4645 #include \"guestfs.h\"
4646 #include \"guestfs-internal-actions.h\"
4647 #include \"guestfs_protocol.h\"
4648
4649 #define error guestfs_error
4650 //#define perrorf guestfs_perrorf
4651 //#define safe_malloc guestfs_safe_malloc
4652 #define safe_realloc guestfs_safe_realloc
4653 //#define safe_strdup guestfs_safe_strdup
4654 #define safe_memdup guestfs_safe_memdup
4655
4656 /* Check the return message from a call for validity. */
4657 static int
4658 check_reply_header (guestfs_h *g,
4659                     const struct guestfs_message_header *hdr,
4660                     unsigned int proc_nr, unsigned int serial)
4661 {
4662   if (hdr->prog != GUESTFS_PROGRAM) {
4663     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
4664     return -1;
4665   }
4666   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
4667     error (g, \"wrong protocol version (%%d/%%d)\",
4668            hdr->vers, GUESTFS_PROTOCOL_VERSION);
4669     return -1;
4670   }
4671   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
4672     error (g, \"unexpected message direction (%%d/%%d)\",
4673            hdr->direction, GUESTFS_DIRECTION_REPLY);
4674     return -1;
4675   }
4676   if (hdr->proc != proc_nr) {
4677     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
4678     return -1;
4679   }
4680   if (hdr->serial != serial) {
4681     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
4682     return -1;
4683   }
4684
4685   return 0;
4686 }
4687
4688 /* Check we are in the right state to run a high-level action. */
4689 static int
4690 check_state (guestfs_h *g, const char *caller)
4691 {
4692   if (!guestfs__is_ready (g)) {
4693     if (guestfs__is_config (g) || guestfs__is_launching (g))
4694       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
4695         caller);
4696     else
4697       error (g, \"%%s called from the wrong state, %%d != READY\",
4698         caller, guestfs__get_state (g));
4699     return -1;
4700   }
4701   return 0;
4702 }
4703
4704 ";
4705
4706   (* Generate code to generate guestfish call traces. *)
4707   let trace_call shortname style =
4708     pr "  if (guestfs__get_trace (g)) {\n";
4709
4710     let needs_i =
4711       List.exists (function
4712                    | StringList _ | DeviceList _ -> true
4713                    | _ -> false) (snd style) in
4714     if needs_i then (
4715       pr "    int i;\n";
4716       pr "\n"
4717     );
4718
4719     pr "    printf (\"%s\");\n" shortname;
4720     List.iter (
4721       function
4722       | String n                        (* strings *)
4723       | Device n
4724       | Pathname n
4725       | Dev_or_Path n
4726       | FileIn n
4727       | FileOut n ->
4728           (* guestfish doesn't support string escaping, so neither do we *)
4729           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
4730       | OptString n ->                  (* string option *)
4731           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
4732           pr "    else printf (\" null\");\n"
4733       | StringList n
4734       | DeviceList n ->                 (* string list *)
4735           pr "    putchar (' ');\n";
4736           pr "    putchar ('\"');\n";
4737           pr "    for (i = 0; %s[i]; ++i) {\n" n;
4738           pr "      if (i > 0) putchar (' ');\n";
4739           pr "      fputs (%s[i], stdout);\n" n;
4740           pr "    }\n";
4741           pr "    putchar ('\"');\n";
4742       | Bool n ->                       (* boolean *)
4743           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
4744       | Int n ->                        (* int *)
4745           pr "    printf (\" %%d\", %s);\n" n
4746     ) (snd style);
4747     pr "    putchar ('\\n');\n";
4748     pr "  }\n";
4749     pr "\n";
4750   in
4751
4752   (* For non-daemon functions, generate a wrapper around each function. *)
4753   List.iter (
4754     fun (shortname, style, _, _, _, _, _) ->
4755       let name = "guestfs_" ^ shortname in
4756
4757       generate_prototype ~extern:false ~semicolon:false ~newline:true
4758         ~handle:"g" name style;
4759       pr "{\n";
4760       trace_call shortname style;
4761       pr "  return guestfs__%s " shortname;
4762       generate_c_call_args ~handle:"g" style;
4763       pr ";\n";
4764       pr "}\n";
4765       pr "\n"
4766   ) non_daemon_functions;
4767
4768   (* Client-side stubs for each function. *)
4769   List.iter (
4770     fun (shortname, style, _, _, _, _, _) ->
4771       let name = "guestfs_" ^ shortname in
4772
4773       (* Generate the action stub. *)
4774       generate_prototype ~extern:false ~semicolon:false ~newline:true
4775         ~handle:"g" name style;
4776
4777       let error_code =
4778         match fst style with
4779         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
4780         | RConstString _ | RConstOptString _ ->
4781             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4782         | RString _ | RStringList _
4783         | RStruct _ | RStructList _
4784         | RHashtable _ | RBufferOut _ ->
4785             "NULL" in
4786
4787       pr "{\n";
4788
4789       (match snd style with
4790        | [] -> ()
4791        | _ -> pr "  struct %s_args args;\n" name
4792       );
4793
4794       pr "  guestfs_message_header hdr;\n";
4795       pr "  guestfs_message_error err;\n";
4796       let has_ret =
4797         match fst style with
4798         | RErr -> false
4799         | RConstString _ | RConstOptString _ ->
4800             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4801         | RInt _ | RInt64 _
4802         | RBool _ | RString _ | RStringList _
4803         | RStruct _ | RStructList _
4804         | RHashtable _ | RBufferOut _ ->
4805             pr "  struct %s_ret ret;\n" name;
4806             true in
4807
4808       pr "  int serial;\n";
4809       pr "  int r;\n";
4810       pr "\n";
4811       trace_call shortname style;
4812       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
4813       pr "  guestfs___set_busy (g);\n";
4814       pr "\n";
4815
4816       (* Send the main header and arguments. *)
4817       (match snd style with
4818        | [] ->
4819            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
4820              (String.uppercase shortname)
4821        | args ->
4822            List.iter (
4823              function
4824              | Pathname n | Device n | Dev_or_Path n | String n ->
4825                  pr "  args.%s = (char *) %s;\n" n n
4826              | OptString n ->
4827                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
4828              | StringList n | DeviceList n ->
4829                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
4830                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
4831              | Bool n ->
4832                  pr "  args.%s = %s;\n" n n
4833              | Int n ->
4834                  pr "  args.%s = %s;\n" n n
4835              | FileIn _ | FileOut _ -> ()
4836            ) args;
4837            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
4838              (String.uppercase shortname);
4839            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
4840              name;
4841       );
4842       pr "  if (serial == -1) {\n";
4843       pr "    guestfs___end_busy (g);\n";
4844       pr "    return %s;\n" error_code;
4845       pr "  }\n";
4846       pr "\n";
4847
4848       (* Send any additional files (FileIn) requested. *)
4849       let need_read_reply_label = ref false in
4850       List.iter (
4851         function
4852         | FileIn n ->
4853             pr "  r = guestfs___send_file (g, %s);\n" n;
4854             pr "  if (r == -1) {\n";
4855             pr "    guestfs___end_busy (g);\n";
4856             pr "    return %s;\n" error_code;
4857             pr "  }\n";
4858             pr "  if (r == -2) /* daemon cancelled */\n";
4859             pr "    goto read_reply;\n";
4860             need_read_reply_label := true;
4861             pr "\n";
4862         | _ -> ()
4863       ) (snd style);
4864
4865       (* Wait for the reply from the remote end. *)
4866       if !need_read_reply_label then pr " read_reply:\n";
4867       pr "  memset (&hdr, 0, sizeof hdr);\n";
4868       pr "  memset (&err, 0, sizeof err);\n";
4869       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
4870       pr "\n";
4871       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
4872       if not has_ret then
4873         pr "NULL, NULL"
4874       else
4875         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
4876       pr ");\n";
4877
4878       pr "  if (r == -1) {\n";
4879       pr "    guestfs___end_busy (g);\n";
4880       pr "    return %s;\n" error_code;
4881       pr "  }\n";
4882       pr "\n";
4883
4884       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
4885         (String.uppercase shortname);
4886       pr "    guestfs___end_busy (g);\n";
4887       pr "    return %s;\n" error_code;
4888       pr "  }\n";
4889       pr "\n";
4890
4891       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
4892       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
4893       pr "    free (err.error_message);\n";
4894       pr "    guestfs___end_busy (g);\n";
4895       pr "    return %s;\n" error_code;
4896       pr "  }\n";
4897       pr "\n";
4898
4899       (* Expecting to receive further files (FileOut)? *)
4900       List.iter (
4901         function
4902         | FileOut n ->
4903             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
4904             pr "    guestfs___end_busy (g);\n";
4905             pr "    return %s;\n" error_code;
4906             pr "  }\n";
4907             pr "\n";
4908         | _ -> ()
4909       ) (snd style);
4910
4911       pr "  guestfs___end_busy (g);\n";
4912
4913       (match fst style with
4914        | RErr -> pr "  return 0;\n"
4915        | RInt n | RInt64 n | RBool n ->
4916            pr "  return ret.%s;\n" n
4917        | RConstString _ | RConstOptString _ ->
4918            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
4919        | RString n ->
4920            pr "  return ret.%s; /* caller will free */\n" n
4921        | RStringList n | RHashtable n ->
4922            pr "  /* caller will free this, but we need to add a NULL entry */\n";
4923            pr "  ret.%s.%s_val =\n" n n;
4924            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
4925            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
4926              n n;
4927            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
4928            pr "  return ret.%s.%s_val;\n" n n
4929        | RStruct (n, _) ->
4930            pr "  /* caller will free this */\n";
4931            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4932        | RStructList (n, _) ->
4933            pr "  /* caller will free this */\n";
4934            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
4935        | RBufferOut n ->
4936            pr "  *size_r = ret.%s.%s_len;\n" n n;
4937            pr "  return ret.%s.%s_val; /* caller will free */\n" n n
4938       );
4939
4940       pr "}\n\n"
4941   ) daemon_functions;
4942
4943   (* Functions to free structures. *)
4944   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
4945   pr " * structure format is identical to the XDR format.  See note in\n";
4946   pr " * generator.ml.\n";
4947   pr " */\n";
4948   pr "\n";
4949
4950   List.iter (
4951     fun (typ, _) ->
4952       pr "void\n";
4953       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
4954       pr "{\n";
4955       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
4956       pr "  free (x);\n";
4957       pr "}\n";
4958       pr "\n";
4959
4960       pr "void\n";
4961       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
4962       pr "{\n";
4963       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
4964       pr "  free (x);\n";
4965       pr "}\n";
4966       pr "\n";
4967
4968   ) structs;
4969
4970 (* Generate daemon/actions.h. *)
4971 and generate_daemon_actions_h () =
4972   generate_header CStyle GPLv2;
4973
4974   pr "#include \"../src/guestfs_protocol.h\"\n";
4975   pr "\n";
4976
4977   List.iter (
4978     fun (name, style, _, _, _, _, _) ->
4979       generate_prototype
4980         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
4981         name style;
4982   ) daemon_functions
4983
4984 (* Generate the server-side stubs. *)
4985 and generate_daemon_actions () =
4986   generate_header CStyle GPLv2;
4987
4988   pr "#include <config.h>\n";
4989   pr "\n";
4990   pr "#include <stdio.h>\n";
4991   pr "#include <stdlib.h>\n";
4992   pr "#include <string.h>\n";
4993   pr "#include <inttypes.h>\n";
4994   pr "#include <rpc/types.h>\n";
4995   pr "#include <rpc/xdr.h>\n";
4996   pr "\n";
4997   pr "#include \"daemon.h\"\n";
4998   pr "#include \"c-ctype.h\"\n";
4999   pr "#include \"../src/guestfs_protocol.h\"\n";
5000   pr "#include \"actions.h\"\n";
5001   pr "\n";
5002
5003   List.iter (
5004     fun (name, style, _, _, _, _, _) ->
5005       (* Generate server-side stubs. *)
5006       pr "static void %s_stub (XDR *xdr_in)\n" name;
5007       pr "{\n";
5008       let error_code =
5009         match fst style with
5010         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5011         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5012         | RBool _ -> pr "  int r;\n"; "-1"
5013         | RConstString _ | RConstOptString _ ->
5014             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5015         | RString _ -> pr "  char *r;\n"; "NULL"
5016         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5017         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5018         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5019         | RBufferOut _ ->
5020             pr "  size_t size;\n";
5021             pr "  char *r;\n";
5022             "NULL" in
5023
5024       (match snd style with
5025        | [] -> ()
5026        | args ->
5027            pr "  struct guestfs_%s_args args;\n" name;
5028            List.iter (
5029              function
5030              | Device n | Dev_or_Path n
5031              | Pathname n
5032              | String n -> ()
5033              | OptString n -> pr "  char *%s;\n" n
5034              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5035              | Bool n -> pr "  int %s;\n" n
5036              | Int n -> pr "  int %s;\n" n
5037              | FileIn _ | FileOut _ -> ()
5038            ) args
5039       );
5040       pr "\n";
5041
5042       (match snd style with
5043        | [] -> ()
5044        | args ->
5045            pr "  memset (&args, 0, sizeof args);\n";
5046            pr "\n";
5047            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5048            pr "    reply_with_error (\"%%s: daemon failed to decode procedure arguments\", \"%s\");\n" name;
5049            pr "    return;\n";
5050            pr "  }\n";
5051            let pr_args n =
5052              pr "  char *%s = args.%s;\n" n n
5053            in
5054            let pr_list_handling_code n =
5055              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5056              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5057              pr "  if (%s == NULL) {\n" n;
5058              pr "    reply_with_perror (\"realloc\");\n";
5059              pr "    goto done;\n";
5060              pr "  }\n";
5061              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5062              pr "  args.%s.%s_val = %s;\n" n n n;
5063            in
5064            List.iter (
5065              function
5066              | Pathname n ->
5067                  pr_args n;
5068                  pr "  ABS_PATH (%s, goto done);\n" n;
5069              | Device n ->
5070                  pr_args n;
5071                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5072              | Dev_or_Path n ->
5073                  pr_args n;
5074                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5075              | String n -> pr_args n
5076              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5077              | StringList n ->
5078                  pr_list_handling_code n;
5079              | DeviceList n ->
5080                  pr_list_handling_code n;
5081                  pr "  /* Ensure that each is a device,\n";
5082                  pr "   * and perform device name translation. */\n";
5083                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5084                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5085                  pr "  }\n";
5086              | Bool n -> pr "  %s = args.%s;\n" n n
5087              | Int n -> pr "  %s = args.%s;\n" n n
5088              | FileIn _ | FileOut _ -> ()
5089            ) args;
5090            pr "\n"
5091       );
5092
5093
5094       (* this is used at least for do_equal *)
5095       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5096         (* Emit NEED_ROOT just once, even when there are two or
5097            more Pathname args *)
5098         pr "  NEED_ROOT (goto done);\n";
5099       );
5100
5101       (* Don't want to call the impl with any FileIn or FileOut
5102        * parameters, since these go "outside" the RPC protocol.
5103        *)
5104       let args' =
5105         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5106           (snd style) in
5107       pr "  r = do_%s " name;
5108       generate_c_call_args (fst style, args');
5109       pr ";\n";
5110
5111       pr "  if (r == %s)\n" error_code;
5112       pr "    /* do_%s has already called reply_with_error */\n" name;
5113       pr "    goto done;\n";
5114       pr "\n";
5115
5116       (* If there are any FileOut parameters, then the impl must
5117        * send its own reply.
5118        *)
5119       let no_reply =
5120         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5121       if no_reply then
5122         pr "  /* do_%s has already sent a reply */\n" name
5123       else (
5124         match fst style with
5125         | RErr -> pr "  reply (NULL, NULL);\n"
5126         | RInt n | RInt64 n | RBool n ->
5127             pr "  struct guestfs_%s_ret ret;\n" name;
5128             pr "  ret.%s = r;\n" n;
5129             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5130               name
5131         | RConstString _ | RConstOptString _ ->
5132             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5133         | RString n ->
5134             pr "  struct guestfs_%s_ret ret;\n" name;
5135             pr "  ret.%s = r;\n" n;
5136             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5137               name;
5138             pr "  free (r);\n"
5139         | RStringList n | RHashtable n ->
5140             pr "  struct guestfs_%s_ret ret;\n" name;
5141             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5142             pr "  ret.%s.%s_val = r;\n" n n;
5143             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5144               name;
5145             pr "  free_strings (r);\n"
5146         | RStruct (n, _) ->
5147             pr "  struct guestfs_%s_ret ret;\n" name;
5148             pr "  ret.%s = *r;\n" n;
5149             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5150               name;
5151             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5152               name
5153         | RStructList (n, _) ->
5154             pr "  struct guestfs_%s_ret ret;\n" name;
5155             pr "  ret.%s = *r;\n" n;
5156             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5157               name;
5158             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5159               name
5160         | RBufferOut n ->
5161             pr "  struct guestfs_%s_ret ret;\n" name;
5162             pr "  ret.%s.%s_val = r;\n" n n;
5163             pr "  ret.%s.%s_len = size;\n" n n;
5164             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5165               name;
5166             pr "  free (r);\n"
5167       );
5168
5169       (* Free the args. *)
5170       (match snd style with
5171        | [] ->
5172            pr "done: ;\n";
5173        | _ ->
5174            pr "done:\n";
5175            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5176              name
5177       );
5178
5179       pr "}\n\n";
5180   ) daemon_functions;
5181
5182   (* Dispatch function. *)
5183   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5184   pr "{\n";
5185   pr "  switch (proc_nr) {\n";
5186
5187   List.iter (
5188     fun (name, style, _, _, _, _, _) ->
5189       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5190       pr "      %s_stub (xdr_in);\n" name;
5191       pr "      break;\n"
5192   ) daemon_functions;
5193
5194   pr "    default:\n";
5195   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";
5196   pr "  }\n";
5197   pr "}\n";
5198   pr "\n";
5199
5200   (* LVM columns and tokenization functions. *)
5201   (* XXX This generates crap code.  We should rethink how we
5202    * do this parsing.
5203    *)
5204   List.iter (
5205     function
5206     | typ, cols ->
5207         pr "static const char *lvm_%s_cols = \"%s\";\n"
5208           typ (String.concat "," (List.map fst cols));
5209         pr "\n";
5210
5211         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5212         pr "{\n";
5213         pr "  char *tok, *p, *next;\n";
5214         pr "  int i, j;\n";
5215         pr "\n";
5216         (*
5217           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5218           pr "\n";
5219         *)
5220         pr "  if (!str) {\n";
5221         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
5222         pr "    return -1;\n";
5223         pr "  }\n";
5224         pr "  if (!*str || c_isspace (*str)) {\n";
5225         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
5226         pr "    return -1;\n";
5227         pr "  }\n";
5228         pr "  tok = str;\n";
5229         List.iter (
5230           fun (name, coltype) ->
5231             pr "  if (!tok) {\n";
5232             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
5233             pr "    return -1;\n";
5234             pr "  }\n";
5235             pr "  p = strchrnul (tok, ',');\n";
5236             pr "  if (*p) next = p+1; else next = NULL;\n";
5237             pr "  *p = '\\0';\n";
5238             (match coltype with
5239              | FString ->
5240                  pr "  r->%s = strdup (tok);\n" name;
5241                  pr "  if (r->%s == NULL) {\n" name;
5242                  pr "    perror (\"strdup\");\n";
5243                  pr "    return -1;\n";
5244                  pr "  }\n"
5245              | FUUID ->
5246                  pr "  for (i = j = 0; i < 32; ++j) {\n";
5247                  pr "    if (tok[j] == '\\0') {\n";
5248                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
5249                  pr "      return -1;\n";
5250                  pr "    } else if (tok[j] != '-')\n";
5251                  pr "      r->%s[i++] = tok[j];\n" name;
5252                  pr "  }\n";
5253              | FBytes ->
5254                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
5255                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5256                  pr "    return -1;\n";
5257                  pr "  }\n";
5258              | FInt64 ->
5259                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
5260                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5261                  pr "    return -1;\n";
5262                  pr "  }\n";
5263              | FOptPercent ->
5264                  pr "  if (tok[0] == '\\0')\n";
5265                  pr "    r->%s = -1;\n" name;
5266                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
5267                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
5268                  pr "    return -1;\n";
5269                  pr "  }\n";
5270              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
5271                  assert false (* can never be an LVM column *)
5272             );
5273             pr "  tok = next;\n";
5274         ) cols;
5275
5276         pr "  if (tok != NULL) {\n";
5277         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
5278         pr "    return -1;\n";
5279         pr "  }\n";
5280         pr "  return 0;\n";
5281         pr "}\n";
5282         pr "\n";
5283
5284         pr "guestfs_int_lvm_%s_list *\n" typ;
5285         pr "parse_command_line_%ss (void)\n" typ;
5286         pr "{\n";
5287         pr "  char *out, *err;\n";
5288         pr "  char *p, *pend;\n";
5289         pr "  int r, i;\n";
5290         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
5291         pr "  void *newp;\n";
5292         pr "\n";
5293         pr "  ret = malloc (sizeof *ret);\n";
5294         pr "  if (!ret) {\n";
5295         pr "    reply_with_perror (\"malloc\");\n";
5296         pr "    return NULL;\n";
5297         pr "  }\n";
5298         pr "\n";
5299         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
5300         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
5301         pr "\n";
5302         pr "  r = command (&out, &err,\n";
5303         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
5304         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
5305         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
5306         pr "  if (r == -1) {\n";
5307         pr "    reply_with_error (\"%%s\", err);\n";
5308         pr "    free (out);\n";
5309         pr "    free (err);\n";
5310         pr "    free (ret);\n";
5311         pr "    return NULL;\n";
5312         pr "  }\n";
5313         pr "\n";
5314         pr "  free (err);\n";
5315         pr "\n";
5316         pr "  /* Tokenize each line of the output. */\n";
5317         pr "  p = out;\n";
5318         pr "  i = 0;\n";
5319         pr "  while (p) {\n";
5320         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
5321         pr "    if (pend) {\n";
5322         pr "      *pend = '\\0';\n";
5323         pr "      pend++;\n";
5324         pr "    }\n";
5325         pr "\n";
5326         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
5327         pr "      p++;\n";
5328         pr "\n";
5329         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
5330         pr "      p = pend;\n";
5331         pr "      continue;\n";
5332         pr "    }\n";
5333         pr "\n";
5334         pr "    /* Allocate some space to store this next entry. */\n";
5335         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
5336         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
5337         pr "    if (newp == NULL) {\n";
5338         pr "      reply_with_perror (\"realloc\");\n";
5339         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5340         pr "      free (ret);\n";
5341         pr "      free (out);\n";
5342         pr "      return NULL;\n";
5343         pr "    }\n";
5344         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
5345         pr "\n";
5346         pr "    /* Tokenize the next entry. */\n";
5347         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
5348         pr "    if (r == -1) {\n";
5349         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
5350         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
5351         pr "      free (ret);\n";
5352         pr "      free (out);\n";
5353         pr "      return NULL;\n";
5354         pr "    }\n";
5355         pr "\n";
5356         pr "    ++i;\n";
5357         pr "    p = pend;\n";
5358         pr "  }\n";
5359         pr "\n";
5360         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
5361         pr "\n";
5362         pr "  free (out);\n";
5363         pr "  return ret;\n";
5364         pr "}\n"
5365
5366   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
5367
5368 (* Generate a list of function names, for debugging in the daemon.. *)
5369 and generate_daemon_names () =
5370   generate_header CStyle GPLv2;
5371
5372   pr "#include <config.h>\n";
5373   pr "\n";
5374   pr "#include \"daemon.h\"\n";
5375   pr "\n";
5376
5377   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
5378   pr "const char *function_names[] = {\n";
5379   List.iter (
5380     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
5381   ) daemon_functions;
5382   pr "};\n";
5383
5384 (* Generate the tests. *)
5385 and generate_tests () =
5386   generate_header CStyle GPLv2;
5387
5388   pr "\
5389 #include <stdio.h>
5390 #include <stdlib.h>
5391 #include <string.h>
5392 #include <unistd.h>
5393 #include <sys/types.h>
5394 #include <fcntl.h>
5395
5396 #include \"guestfs.h\"
5397
5398 static guestfs_h *g;
5399 static int suppress_error = 0;
5400
5401 static void print_error (guestfs_h *g, void *data, const char *msg)
5402 {
5403   if (!suppress_error)
5404     fprintf (stderr, \"%%s\\n\", msg);
5405 }
5406
5407 /* FIXME: nearly identical code appears in fish.c */
5408 static void print_strings (char *const *argv)
5409 {
5410   int argc;
5411
5412   for (argc = 0; argv[argc] != NULL; ++argc)
5413     printf (\"\\t%%s\\n\", argv[argc]);
5414 }
5415
5416 /*
5417 static void print_table (char const *const *argv)
5418 {
5419   int i;
5420
5421   for (i = 0; argv[i] != NULL; i += 2)
5422     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
5423 }
5424 */
5425
5426 ";
5427
5428   (* Generate a list of commands which are not tested anywhere. *)
5429   pr "static void no_test_warnings (void)\n";
5430   pr "{\n";
5431
5432   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
5433   List.iter (
5434     fun (_, _, _, _, tests, _, _) ->
5435       let tests = filter_map (
5436         function
5437         | (_, (Always|If _|Unless _), test) -> Some test
5438         | (_, Disabled, _) -> None
5439       ) tests in
5440       let seq = List.concat (List.map seq_of_test tests) in
5441       let cmds_tested = List.map List.hd seq in
5442       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
5443   ) all_functions;
5444
5445   List.iter (
5446     fun (name, _, _, _, _, _, _) ->
5447       if not (Hashtbl.mem hash name) then
5448         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
5449   ) all_functions;
5450
5451   pr "}\n";
5452   pr "\n";
5453
5454   (* Generate the actual tests.  Note that we generate the tests
5455    * in reverse order, deliberately, so that (in general) the
5456    * newest tests run first.  This makes it quicker and easier to
5457    * debug them.
5458    *)
5459   let test_names =
5460     List.map (
5461       fun (name, _, _, _, tests, _, _) ->
5462         mapi (generate_one_test name) tests
5463     ) (List.rev all_functions) in
5464   let test_names = List.concat test_names in
5465   let nr_tests = List.length test_names in
5466
5467   pr "\
5468 int main (int argc, char *argv[])
5469 {
5470   char c = 0;
5471   unsigned long int n_failed = 0;
5472   const char *filename;
5473   int fd;
5474   int nr_tests, test_num = 0;
5475
5476   setbuf (stdout, NULL);
5477
5478   no_test_warnings ();
5479
5480   g = guestfs_create ();
5481   if (g == NULL) {
5482     printf (\"guestfs_create FAILED\\n\");
5483     exit (1);
5484   }
5485
5486   guestfs_set_error_handler (g, print_error, NULL);
5487
5488   guestfs_set_path (g, \"../appliance\");
5489
5490   filename = \"test1.img\";
5491   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5492   if (fd == -1) {
5493     perror (filename);
5494     exit (1);
5495   }
5496   if (lseek (fd, %d, SEEK_SET) == -1) {
5497     perror (\"lseek\");
5498     close (fd);
5499     unlink (filename);
5500     exit (1);
5501   }
5502   if (write (fd, &c, 1) == -1) {
5503     perror (\"write\");
5504     close (fd);
5505     unlink (filename);
5506     exit (1);
5507   }
5508   if (close (fd) == -1) {
5509     perror (filename);
5510     unlink (filename);
5511     exit (1);
5512   }
5513   if (guestfs_add_drive (g, filename) == -1) {
5514     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5515     exit (1);
5516   }
5517
5518   filename = \"test2.img\";
5519   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5520   if (fd == -1) {
5521     perror (filename);
5522     exit (1);
5523   }
5524   if (lseek (fd, %d, SEEK_SET) == -1) {
5525     perror (\"lseek\");
5526     close (fd);
5527     unlink (filename);
5528     exit (1);
5529   }
5530   if (write (fd, &c, 1) == -1) {
5531     perror (\"write\");
5532     close (fd);
5533     unlink (filename);
5534     exit (1);
5535   }
5536   if (close (fd) == -1) {
5537     perror (filename);
5538     unlink (filename);
5539     exit (1);
5540   }
5541   if (guestfs_add_drive (g, filename) == -1) {
5542     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5543     exit (1);
5544   }
5545
5546   filename = \"test3.img\";
5547   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
5548   if (fd == -1) {
5549     perror (filename);
5550     exit (1);
5551   }
5552   if (lseek (fd, %d, SEEK_SET) == -1) {
5553     perror (\"lseek\");
5554     close (fd);
5555     unlink (filename);
5556     exit (1);
5557   }
5558   if (write (fd, &c, 1) == -1) {
5559     perror (\"write\");
5560     close (fd);
5561     unlink (filename);
5562     exit (1);
5563   }
5564   if (close (fd) == -1) {
5565     perror (filename);
5566     unlink (filename);
5567     exit (1);
5568   }
5569   if (guestfs_add_drive (g, filename) == -1) {
5570     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
5571     exit (1);
5572   }
5573
5574   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
5575     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
5576     exit (1);
5577   }
5578
5579   if (guestfs_launch (g) == -1) {
5580     printf (\"guestfs_launch FAILED\\n\");
5581     exit (1);
5582   }
5583
5584   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
5585   alarm (600);
5586
5587   /* Cancel previous alarm. */
5588   alarm (0);
5589
5590   nr_tests = %d;
5591
5592 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
5593
5594   iteri (
5595     fun i test_name ->
5596       pr "  test_num++;\n";
5597       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
5598       pr "  if (%s () == -1) {\n" test_name;
5599       pr "    printf (\"%s FAILED\\n\");\n" test_name;
5600       pr "    n_failed++;\n";
5601       pr "  }\n";
5602   ) test_names;
5603   pr "\n";
5604
5605   pr "  guestfs_close (g);\n";
5606   pr "  unlink (\"test1.img\");\n";
5607   pr "  unlink (\"test2.img\");\n";
5608   pr "  unlink (\"test3.img\");\n";
5609   pr "\n";
5610
5611   pr "  if (n_failed > 0) {\n";
5612   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
5613   pr "    exit (1);\n";
5614   pr "  }\n";
5615   pr "\n";
5616
5617   pr "  exit (0);\n";
5618   pr "}\n"
5619
5620 and generate_one_test name i (init, prereq, test) =
5621   let test_name = sprintf "test_%s_%d" name i in
5622
5623   pr "\
5624 static int %s_skip (void)
5625 {
5626   const char *str;
5627
5628   str = getenv (\"TEST_ONLY\");
5629   if (str)
5630     return strstr (str, \"%s\") == NULL;
5631   str = getenv (\"SKIP_%s\");
5632   if (str && strcmp (str, \"1\") == 0) return 1;
5633   str = getenv (\"SKIP_TEST_%s\");
5634   if (str && strcmp (str, \"1\") == 0) return 1;
5635   return 0;
5636 }
5637
5638 " test_name name (String.uppercase test_name) (String.uppercase name);
5639
5640   (match prereq with
5641    | Disabled | Always -> ()
5642    | If code | Unless code ->
5643        pr "static int %s_prereq (void)\n" test_name;
5644        pr "{\n";
5645        pr "  %s\n" code;
5646        pr "}\n";
5647        pr "\n";
5648   );
5649
5650   pr "\
5651 static int %s (void)
5652 {
5653   if (%s_skip ()) {
5654     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
5655     return 0;
5656   }
5657
5658 " test_name test_name test_name;
5659
5660   (match prereq with
5661    | Disabled ->
5662        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
5663    | If _ ->
5664        pr "  if (! %s_prereq ()) {\n" test_name;
5665        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5666        pr "    return 0;\n";
5667        pr "  }\n";
5668        pr "\n";
5669        generate_one_test_body name i test_name init test;
5670    | Unless _ ->
5671        pr "  if (%s_prereq ()) {\n" test_name;
5672        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
5673        pr "    return 0;\n";
5674        pr "  }\n";
5675        pr "\n";
5676        generate_one_test_body name i test_name init test;
5677    | Always ->
5678        generate_one_test_body name i test_name init test
5679   );
5680
5681   pr "  return 0;\n";
5682   pr "}\n";
5683   pr "\n";
5684   test_name
5685
5686 and generate_one_test_body name i test_name init test =
5687   (match init with
5688    | InitNone (* XXX at some point, InitNone and InitEmpty became
5689                * folded together as the same thing.  Really we should
5690                * make InitNone do nothing at all, but the tests may
5691                * need to be checked to make sure this is OK.
5692                *)
5693    | InitEmpty ->
5694        pr "  /* InitNone|InitEmpty 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    | InitPartition ->
5700        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
5701        List.iter (generate_test_command_call test_name)
5702          [["blockdev_setrw"; "/dev/sda"];
5703           ["umount_all"];
5704           ["lvm_remove_all"];
5705           ["sfdiskM"; "/dev/sda"; ","]]
5706    | InitBasicFS ->
5707        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
5708        List.iter (generate_test_command_call test_name)
5709          [["blockdev_setrw"; "/dev/sda"];
5710           ["umount_all"];
5711           ["lvm_remove_all"];
5712           ["sfdiskM"; "/dev/sda"; ","];
5713           ["mkfs"; "ext2"; "/dev/sda1"];
5714           ["mount"; "/dev/sda1"; "/"]]
5715    | InitBasicFSonLVM ->
5716        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
5717          test_name;
5718        List.iter (generate_test_command_call test_name)
5719          [["blockdev_setrw"; "/dev/sda"];
5720           ["umount_all"];
5721           ["lvm_remove_all"];
5722           ["sfdiskM"; "/dev/sda"; ","];
5723           ["pvcreate"; "/dev/sda1"];
5724           ["vgcreate"; "VG"; "/dev/sda1"];
5725           ["lvcreate"; "LV"; "VG"; "8"];
5726           ["mkfs"; "ext2"; "/dev/VG/LV"];
5727           ["mount"; "/dev/VG/LV"; "/"]]
5728    | InitISOFS ->
5729        pr "  /* InitISOFS for %s */\n" test_name;
5730        List.iter (generate_test_command_call test_name)
5731          [["blockdev_setrw"; "/dev/sda"];
5732           ["umount_all"];
5733           ["lvm_remove_all"];
5734           ["mount_ro"; "/dev/sdd"; "/"]]
5735   );
5736
5737   let get_seq_last = function
5738     | [] ->
5739         failwithf "%s: you cannot use [] (empty list) when expecting a command"
5740           test_name
5741     | seq ->
5742         let seq = List.rev seq in
5743         List.rev (List.tl seq), List.hd seq
5744   in
5745
5746   match test with
5747   | TestRun seq ->
5748       pr "  /* TestRun for %s (%d) */\n" name i;
5749       List.iter (generate_test_command_call test_name) seq
5750   | TestOutput (seq, expected) ->
5751       pr "  /* TestOutput for %s (%d) */\n" name i;
5752       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5753       let seq, last = get_seq_last seq in
5754       let test () =
5755         pr "    if (strcmp (r, expected) != 0) {\n";
5756         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5757         pr "      return -1;\n";
5758         pr "    }\n"
5759       in
5760       List.iter (generate_test_command_call test_name) seq;
5761       generate_test_command_call ~test test_name last
5762   | TestOutputList (seq, expected) ->
5763       pr "  /* TestOutputList for %s (%d) */\n" name i;
5764       let seq, last = get_seq_last seq in
5765       let test () =
5766         iteri (
5767           fun i str ->
5768             pr "    if (!r[%d]) {\n" i;
5769             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5770             pr "      print_strings (r);\n";
5771             pr "      return -1;\n";
5772             pr "    }\n";
5773             pr "    {\n";
5774             pr "      const char *expected = \"%s\";\n" (c_quote str);
5775             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5776             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5777             pr "        return -1;\n";
5778             pr "      }\n";
5779             pr "    }\n"
5780         ) expected;
5781         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5782         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5783           test_name;
5784         pr "      print_strings (r);\n";
5785         pr "      return -1;\n";
5786         pr "    }\n"
5787       in
5788       List.iter (generate_test_command_call test_name) seq;
5789       generate_test_command_call ~test test_name last
5790   | TestOutputListOfDevices (seq, expected) ->
5791       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
5792       let seq, last = get_seq_last seq in
5793       let test () =
5794         iteri (
5795           fun i str ->
5796             pr "    if (!r[%d]) {\n" i;
5797             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
5798             pr "      print_strings (r);\n";
5799             pr "      return -1;\n";
5800             pr "    }\n";
5801             pr "    {\n";
5802             pr "      const char *expected = \"%s\";\n" (c_quote str);
5803             pr "      r[%d][5] = 's';\n" i;
5804             pr "      if (strcmp (r[%d], expected) != 0) {\n" i;
5805             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
5806             pr "        return -1;\n";
5807             pr "      }\n";
5808             pr "    }\n"
5809         ) expected;
5810         pr "    if (r[%d] != NULL) {\n" (List.length expected);
5811         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
5812           test_name;
5813         pr "      print_strings (r);\n";
5814         pr "      return -1;\n";
5815         pr "    }\n"
5816       in
5817       List.iter (generate_test_command_call test_name) seq;
5818       generate_test_command_call ~test test_name last
5819   | TestOutputInt (seq, expected) ->
5820       pr "  /* TestOutputInt for %s (%d) */\n" name i;
5821       let seq, last = get_seq_last seq in
5822       let test () =
5823         pr "    if (r != %d) {\n" expected;
5824         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
5825           test_name expected;
5826         pr "               (int) r);\n";
5827         pr "      return -1;\n";
5828         pr "    }\n"
5829       in
5830       List.iter (generate_test_command_call test_name) seq;
5831       generate_test_command_call ~test test_name last
5832   | TestOutputIntOp (seq, op, expected) ->
5833       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
5834       let seq, last = get_seq_last seq in
5835       let test () =
5836         pr "    if (! (r %s %d)) {\n" op expected;
5837         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
5838           test_name op expected;
5839         pr "               (int) r);\n";
5840         pr "      return -1;\n";
5841         pr "    }\n"
5842       in
5843       List.iter (generate_test_command_call test_name) seq;
5844       generate_test_command_call ~test test_name last
5845   | TestOutputTrue seq ->
5846       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
5847       let seq, last = get_seq_last seq in
5848       let test () =
5849         pr "    if (!r) {\n";
5850         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
5851           test_name;
5852         pr "      return -1;\n";
5853         pr "    }\n"
5854       in
5855       List.iter (generate_test_command_call test_name) seq;
5856       generate_test_command_call ~test test_name last
5857   | TestOutputFalse seq ->
5858       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
5859       let seq, last = get_seq_last seq in
5860       let test () =
5861         pr "    if (r) {\n";
5862         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
5863           test_name;
5864         pr "      return -1;\n";
5865         pr "    }\n"
5866       in
5867       List.iter (generate_test_command_call test_name) seq;
5868       generate_test_command_call ~test test_name last
5869   | TestOutputLength (seq, expected) ->
5870       pr "  /* TestOutputLength for %s (%d) */\n" name i;
5871       let seq, last = get_seq_last seq in
5872       let test () =
5873         pr "    int j;\n";
5874         pr "    for (j = 0; j < %d; ++j)\n" expected;
5875         pr "      if (r[j] == NULL) {\n";
5876         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
5877           test_name;
5878         pr "        print_strings (r);\n";
5879         pr "        return -1;\n";
5880         pr "      }\n";
5881         pr "    if (r[j] != NULL) {\n";
5882         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
5883           test_name;
5884         pr "      print_strings (r);\n";
5885         pr "      return -1;\n";
5886         pr "    }\n"
5887       in
5888       List.iter (generate_test_command_call test_name) seq;
5889       generate_test_command_call ~test test_name last
5890   | TestOutputBuffer (seq, expected) ->
5891       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
5892       pr "  const char *expected = \"%s\";\n" (c_quote expected);
5893       let seq, last = get_seq_last seq in
5894       let len = String.length expected in
5895       let test () =
5896         pr "    if (size != %d) {\n" len;
5897         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
5898         pr "      return -1;\n";
5899         pr "    }\n";
5900         pr "    if (strncmp (r, expected, size) != 0) {\n";
5901         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
5902         pr "      return -1;\n";
5903         pr "    }\n"
5904       in
5905       List.iter (generate_test_command_call test_name) seq;
5906       generate_test_command_call ~test test_name last
5907   | TestOutputStruct (seq, checks) ->
5908       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
5909       let seq, last = get_seq_last seq in
5910       let test () =
5911         List.iter (
5912           function
5913           | CompareWithInt (field, expected) ->
5914               pr "    if (r->%s != %d) {\n" field expected;
5915               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
5916                 test_name field expected;
5917               pr "               (int) r->%s);\n" field;
5918               pr "      return -1;\n";
5919               pr "    }\n"
5920           | CompareWithIntOp (field, op, expected) ->
5921               pr "    if (!(r->%s %s %d)) {\n" field op expected;
5922               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
5923                 test_name field op expected;
5924               pr "               (int) r->%s);\n" field;
5925               pr "      return -1;\n";
5926               pr "    }\n"
5927           | CompareWithString (field, expected) ->
5928               pr "    if (strcmp (r->%s, \"%s\") != 0) {\n" field expected;
5929               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
5930                 test_name field expected;
5931               pr "               r->%s);\n" field;
5932               pr "      return -1;\n";
5933               pr "    }\n"
5934           | CompareFieldsIntEq (field1, field2) ->
5935               pr "    if (r->%s != r->%s) {\n" field1 field2;
5936               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
5937                 test_name field1 field2;
5938               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
5939               pr "      return -1;\n";
5940               pr "    }\n"
5941           | CompareFieldsStrEq (field1, field2) ->
5942               pr "    if (strcmp (r->%s, r->%s) != 0) {\n" field1 field2;
5943               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
5944                 test_name field1 field2;
5945               pr "               r->%s, r->%s);\n" field1 field2;
5946               pr "      return -1;\n";
5947               pr "    }\n"
5948         ) checks
5949       in
5950       List.iter (generate_test_command_call test_name) seq;
5951       generate_test_command_call ~test test_name last
5952   | TestLastFail seq ->
5953       pr "  /* TestLastFail for %s (%d) */\n" name i;
5954       let seq, last = get_seq_last seq in
5955       List.iter (generate_test_command_call test_name) seq;
5956       generate_test_command_call test_name ~expect_error:true last
5957
5958 (* Generate the code to run a command, leaving the result in 'r'.
5959  * If you expect to get an error then you should set expect_error:true.
5960  *)
5961 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
5962   match cmd with
5963   | [] -> assert false
5964   | name :: args ->
5965       (* Look up the command to find out what args/ret it has. *)
5966       let style =
5967         try
5968           let _, style, _, _, _, _, _ =
5969             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
5970           style
5971         with Not_found ->
5972           failwithf "%s: in test, command %s was not found" test_name name in
5973
5974       if List.length (snd style) <> List.length args then
5975         failwithf "%s: in test, wrong number of args given to %s"
5976           test_name name;
5977
5978       pr "  {\n";
5979
5980       List.iter (
5981         function
5982         | OptString n, "NULL" -> ()
5983         | Pathname n, arg
5984         | Device n, arg
5985         | Dev_or_Path n, arg
5986         | String n, arg
5987         | OptString n, arg ->
5988             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
5989         | Int _, _
5990         | Bool _, _
5991         | FileIn _, _ | FileOut _, _ -> ()
5992         | StringList n, arg | DeviceList n, arg ->
5993             let strs = string_split " " arg in
5994             iteri (
5995               fun i str ->
5996                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
5997             ) strs;
5998             pr "    const char *const %s[] = {\n" n;
5999             iteri (
6000               fun i _ -> pr "      %s_%d,\n" n i
6001             ) strs;
6002             pr "      NULL\n";
6003             pr "    };\n";
6004       ) (List.combine (snd style) args);
6005
6006       let error_code =
6007         match fst style with
6008         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6009         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6010         | RConstString _ | RConstOptString _ ->
6011             pr "    const char *r;\n"; "NULL"
6012         | RString _ -> pr "    char *r;\n"; "NULL"
6013         | RStringList _ | RHashtable _ ->
6014             pr "    char **r;\n";
6015             pr "    int i;\n";
6016             "NULL"
6017         | RStruct (_, typ) ->
6018             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6019         | RStructList (_, typ) ->
6020             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6021         | RBufferOut _ ->
6022             pr "    char *r;\n";
6023             pr "    size_t size;\n";
6024             "NULL" in
6025
6026       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6027       pr "    r = guestfs_%s (g" name;
6028
6029       (* Generate the parameters. *)
6030       List.iter (
6031         function
6032         | OptString _, "NULL" -> pr ", NULL"
6033         | Pathname n, _
6034         | Device n, _ | Dev_or_Path n, _
6035         | String n, _
6036         | OptString n, _ ->
6037             pr ", %s" n
6038         | FileIn _, arg | FileOut _, arg ->
6039             pr ", \"%s\"" (c_quote arg)
6040         | StringList n, _ | DeviceList n, _ ->
6041             pr ", (char **) %s" n
6042         | Int _, arg ->
6043             let i =
6044               try int_of_string arg
6045               with Failure "int_of_string" ->
6046                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6047             pr ", %d" i
6048         | Bool _, arg ->
6049             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6050       ) (List.combine (snd style) args);
6051
6052       (match fst style with
6053        | RBufferOut _ -> pr ", &size"
6054        | _ -> ()
6055       );
6056
6057       pr ");\n";
6058
6059       if not expect_error then
6060         pr "    if (r == %s)\n" error_code
6061       else
6062         pr "    if (r != %s)\n" error_code;
6063       pr "      return -1;\n";
6064
6065       (* Insert the test code. *)
6066       (match test with
6067        | None -> ()
6068        | Some f -> f ()
6069       );
6070
6071       (match fst style with
6072        | RErr | RInt _ | RInt64 _ | RBool _
6073        | RConstString _ | RConstOptString _ -> ()
6074        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6075        | RStringList _ | RHashtable _ ->
6076            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6077            pr "      free (r[i]);\n";
6078            pr "    free (r);\n"
6079        | RStruct (_, typ) ->
6080            pr "    guestfs_free_%s (r);\n" typ
6081        | RStructList (_, typ) ->
6082            pr "    guestfs_free_%s_list (r);\n" typ
6083       );
6084
6085       pr "  }\n"
6086
6087 and c_quote str =
6088   let str = replace_str str "\r" "\\r" in
6089   let str = replace_str str "\n" "\\n" in
6090   let str = replace_str str "\t" "\\t" in
6091   let str = replace_str str "\000" "\\0" in
6092   str
6093
6094 (* Generate a lot of different functions for guestfish. *)
6095 and generate_fish_cmds () =
6096   generate_header CStyle GPLv2;
6097
6098   let all_functions =
6099     List.filter (
6100       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6101     ) all_functions in
6102   let all_functions_sorted =
6103     List.filter (
6104       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6105     ) all_functions_sorted in
6106
6107   pr "#include <stdio.h>\n";
6108   pr "#include <stdlib.h>\n";
6109   pr "#include <string.h>\n";
6110   pr "#include <inttypes.h>\n";
6111   pr "\n";
6112   pr "#include <guestfs.h>\n";
6113   pr "#include \"c-ctype.h\"\n";
6114   pr "#include \"fish.h\"\n";
6115   pr "\n";
6116
6117   (* list_commands function, which implements guestfish -h *)
6118   pr "void list_commands (void)\n";
6119   pr "{\n";
6120   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6121   pr "  list_builtin_commands ();\n";
6122   List.iter (
6123     fun (name, _, _, flags, _, shortdesc, _) ->
6124       let name = replace_char name '_' '-' in
6125       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6126         name shortdesc
6127   ) all_functions_sorted;
6128   pr "  printf (\"    %%s\\n\",";
6129   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6130   pr "}\n";
6131   pr "\n";
6132
6133   (* display_command function, which implements guestfish -h cmd *)
6134   pr "void display_command (const char *cmd)\n";
6135   pr "{\n";
6136   List.iter (
6137     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6138       let name2 = replace_char name '_' '-' in
6139       let alias =
6140         try find_map (function FishAlias n -> Some n | _ -> None) flags
6141         with Not_found -> name in
6142       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6143       let synopsis =
6144         match snd style with
6145         | [] -> name2
6146         | args ->
6147             sprintf "%s <%s>"
6148               name2 (String.concat "> <" (List.map name_of_argt args)) in
6149
6150       let warnings =
6151         if List.mem ProtocolLimitWarning flags then
6152           ("\n\n" ^ protocol_limit_warning)
6153         else "" in
6154
6155       (* For DangerWillRobinson commands, we should probably have
6156        * guestfish prompt before allowing you to use them (especially
6157        * in interactive mode). XXX
6158        *)
6159       let warnings =
6160         warnings ^
6161           if List.mem DangerWillRobinson flags then
6162             ("\n\n" ^ danger_will_robinson)
6163           else "" in
6164
6165       let warnings =
6166         warnings ^
6167           match deprecation_notice flags with
6168           | None -> ""
6169           | Some txt -> "\n\n" ^ txt in
6170
6171       let describe_alias =
6172         if name <> alias then
6173           sprintf "\n\nYou can use '%s' as an alias for this command." alias
6174         else "" in
6175
6176       pr "  if (";
6177       pr "strcasecmp (cmd, \"%s\") == 0" name;
6178       if name <> name2 then
6179         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6180       if name <> alias then
6181         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6182       pr ")\n";
6183       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
6184         name2 shortdesc
6185         (" " ^ synopsis ^ "\n\n" ^ longdesc ^ warnings ^ describe_alias);
6186       pr "  else\n"
6187   ) all_functions;
6188   pr "    display_builtin_command (cmd);\n";
6189   pr "}\n";
6190   pr "\n";
6191
6192   let emit_print_list_function typ =
6193     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
6194       typ typ typ;
6195     pr "{\n";
6196     pr "  unsigned int i;\n";
6197     pr "\n";
6198     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
6199     pr "    printf (\"[%%d] = {\\n\", i);\n";
6200     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
6201     pr "    printf (\"}\\n\");\n";
6202     pr "  }\n";
6203     pr "}\n";
6204     pr "\n";
6205   in
6206
6207   (* print_* functions *)
6208   List.iter (
6209     fun (typ, cols) ->
6210       let needs_i =
6211         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
6212
6213       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
6214       pr "{\n";
6215       if needs_i then (
6216         pr "  unsigned int i;\n";
6217         pr "\n"
6218       );
6219       List.iter (
6220         function
6221         | name, FString ->
6222             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
6223         | name, FUUID ->
6224             pr "  printf (\"%s: \");\n" name;
6225             pr "  for (i = 0; i < 32; ++i)\n";
6226             pr "    printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6227             pr "  printf (\"\\n\");\n"
6228         | name, FBuffer ->
6229             pr "  printf (\"%%s%s: \", indent);\n" name;
6230             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
6231             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
6232             pr "      printf (\"%%s%%c\", indent, %s->%s[i]);\n" typ name;
6233             pr "    else\n";
6234             pr "      printf (\"%%s\\\\x%%02x\", indent, %s->%s[i]);\n" typ name;
6235             pr "  printf (\"\\n\");\n"
6236         | name, (FUInt64|FBytes) ->
6237             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
6238               name typ name
6239         | name, FInt64 ->
6240             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
6241               name typ name
6242         | name, FUInt32 ->
6243             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
6244               name typ name
6245         | name, FInt32 ->
6246             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
6247               name typ name
6248         | name, FChar ->
6249             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
6250               name typ name
6251         | name, FOptPercent ->
6252             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
6253               typ name name typ name;
6254             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
6255       ) cols;
6256       pr "}\n";
6257       pr "\n";
6258   ) structs;
6259
6260   (* Emit a print_TYPE_list function definition only if that function is used. *)
6261   List.iter (
6262     function
6263     | typ, (RStructListOnly | RStructAndList) ->
6264         (* generate the function for typ *)
6265         emit_print_list_function typ
6266     | typ, _ -> () (* empty *)
6267   ) rstructs_used;
6268
6269   (* Emit a print_TYPE function definition only if that function is used. *)
6270   List.iter (
6271     function
6272     | typ, RStructOnly ->
6273         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
6274         pr "{\n";
6275         pr "  print_%s_indent (%s, \"\");\n" typ typ;
6276         pr "}\n";
6277         pr "\n";
6278     | typ, _ -> () (* empty *)
6279   ) rstructs_used;
6280
6281   (* run_<action> actions *)
6282   List.iter (
6283     fun (name, style, _, flags, _, _, _) ->
6284       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
6285       pr "{\n";
6286       (match fst style with
6287        | RErr
6288        | RInt _
6289        | RBool _ -> pr "  int r;\n"
6290        | RInt64 _ -> pr "  int64_t r;\n"
6291        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
6292        | RString _ -> pr "  char *r;\n"
6293        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
6294        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
6295        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
6296        | RBufferOut _ ->
6297            pr "  char *r;\n";
6298            pr "  size_t size;\n";
6299       );
6300       List.iter (
6301         function
6302         | Pathname n
6303         | Device n | Dev_or_Path n
6304         | String n
6305         | OptString n
6306         | FileIn n
6307         | FileOut n -> pr "  const char *%s;\n" n
6308         | StringList n | DeviceList n -> pr "  char **%s;\n" n
6309         | Bool n -> pr "  int %s;\n" n
6310         | Int n -> pr "  int %s;\n" n
6311       ) (snd style);
6312
6313       (* Check and convert parameters. *)
6314       let argc_expected = List.length (snd style) in
6315       pr "  if (argc != %d) {\n" argc_expected;
6316       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
6317         argc_expected;
6318       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
6319       pr "    return -1;\n";
6320       pr "  }\n";
6321       iteri (
6322         fun i ->
6323           function
6324           | Pathname name
6325           | Device name | Dev_or_Path name | String name -> pr "  %s = argv[%d];\n" name i
6326           | OptString name ->
6327               pr "  %s = strcmp (argv[%d], \"\") != 0 ? argv[%d] : NULL;\n"
6328                 name i i
6329           | FileIn name ->
6330               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdin\";\n"
6331                 name i i
6332           | FileOut name ->
6333               pr "  %s = strcmp (argv[%d], \"-\") != 0 ? argv[%d] : \"/dev/stdout\";\n"
6334                 name i i
6335           | StringList name | DeviceList name ->
6336               pr "  %s = parse_string_list (argv[%d]);\n" name i;
6337               pr "  if (%s == NULL) return -1;\n" name;
6338           | Bool name ->
6339               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
6340           | Int name ->
6341               pr "  %s = atoi (argv[%d]);\n" name i
6342       ) (snd style);
6343
6344       (* Call C API function. *)
6345       let fn =
6346         try find_map (function FishAction n -> Some n | _ -> None) flags
6347         with Not_found -> sprintf "guestfs_%s" name in
6348       pr "  r = %s " fn;
6349       generate_c_call_args ~handle:"g" style;
6350       pr ";\n";
6351
6352       List.iter (
6353         function
6354         | Pathname name | Device name | Dev_or_Path name | String name
6355         | OptString name | FileIn name | FileOut name | Bool name
6356         | Int name -> ()
6357         | StringList name | DeviceList name ->
6358             pr "  free_strings (%s);\n" name
6359       ) (snd style);
6360
6361       (* Check return value for errors and display command results. *)
6362       (match fst style with
6363        | RErr -> pr "  return r;\n"
6364        | RInt _ ->
6365            pr "  if (r == -1) return -1;\n";
6366            pr "  printf (\"%%d\\n\", r);\n";
6367            pr "  return 0;\n"
6368        | RInt64 _ ->
6369            pr "  if (r == -1) return -1;\n";
6370            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
6371            pr "  return 0;\n"
6372        | RBool _ ->
6373            pr "  if (r == -1) return -1;\n";
6374            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
6375            pr "  return 0;\n"
6376        | RConstString _ ->
6377            pr "  if (r == NULL) return -1;\n";
6378            pr "  printf (\"%%s\\n\", r);\n";
6379            pr "  return 0;\n"
6380        | RConstOptString _ ->
6381            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
6382            pr "  return 0;\n"
6383        | RString _ ->
6384            pr "  if (r == NULL) return -1;\n";
6385            pr "  printf (\"%%s\\n\", r);\n";
6386            pr "  free (r);\n";
6387            pr "  return 0;\n"
6388        | RStringList _ ->
6389            pr "  if (r == NULL) return -1;\n";
6390            pr "  print_strings (r);\n";
6391            pr "  free_strings (r);\n";
6392            pr "  return 0;\n"
6393        | RStruct (_, typ) ->
6394            pr "  if (r == NULL) return -1;\n";
6395            pr "  print_%s (r);\n" typ;
6396            pr "  guestfs_free_%s (r);\n" typ;
6397            pr "  return 0;\n"
6398        | RStructList (_, typ) ->
6399            pr "  if (r == NULL) return -1;\n";
6400            pr "  print_%s_list (r);\n" typ;
6401            pr "  guestfs_free_%s_list (r);\n" typ;
6402            pr "  return 0;\n"
6403        | RHashtable _ ->
6404            pr "  if (r == NULL) return -1;\n";
6405            pr "  print_table (r);\n";
6406            pr "  free_strings (r);\n";
6407            pr "  return 0;\n"
6408        | RBufferOut _ ->
6409            pr "  if (r == NULL) return -1;\n";
6410            pr "  fwrite (r, size, 1, stdout);\n";
6411            pr "  free (r);\n";
6412            pr "  return 0;\n"
6413       );
6414       pr "}\n";
6415       pr "\n"
6416   ) all_functions;
6417
6418   (* run_action function *)
6419   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
6420   pr "{\n";
6421   List.iter (
6422     fun (name, _, _, flags, _, _, _) ->
6423       let name2 = replace_char name '_' '-' in
6424       let alias =
6425         try find_map (function FishAlias n -> Some n | _ -> None) flags
6426         with Not_found -> name in
6427       pr "  if (";
6428       pr "strcasecmp (cmd, \"%s\") == 0" name;
6429       if name <> name2 then
6430         pr " || strcasecmp (cmd, \"%s\") == 0" name2;
6431       if name <> alias then
6432         pr " || strcasecmp (cmd, \"%s\") == 0" alias;
6433       pr ")\n";
6434       pr "    return run_%s (cmd, argc, argv);\n" name;
6435       pr "  else\n";
6436   ) all_functions;
6437   pr "    {\n";
6438   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
6439   pr "      return -1;\n";
6440   pr "    }\n";
6441   pr "  return 0;\n";
6442   pr "}\n";
6443   pr "\n"
6444
6445 (* Readline completion for guestfish. *)
6446 and generate_fish_completion () =
6447   generate_header CStyle GPLv2;
6448
6449   let all_functions =
6450     List.filter (
6451       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6452     ) all_functions in
6453
6454   pr "\
6455 #include <config.h>
6456
6457 #include <stdio.h>
6458 #include <stdlib.h>
6459 #include <string.h>
6460
6461 #ifdef HAVE_LIBREADLINE
6462 #include <readline/readline.h>
6463 #endif
6464
6465 #include \"fish.h\"
6466
6467 #ifdef HAVE_LIBREADLINE
6468
6469 static const char *const commands[] = {
6470   BUILTIN_COMMANDS_FOR_COMPLETION,
6471 ";
6472
6473   (* Get the commands, including the aliases.  They don't need to be
6474    * sorted - the generator() function just does a dumb linear search.
6475    *)
6476   let commands =
6477     List.map (
6478       fun (name, _, _, flags, _, _, _) ->
6479         let name2 = replace_char name '_' '-' in
6480         let alias =
6481           try find_map (function FishAlias n -> Some n | _ -> None) flags
6482           with Not_found -> name in
6483
6484         if name <> alias then [name2; alias] else [name2]
6485     ) all_functions in
6486   let commands = List.flatten commands in
6487
6488   List.iter (pr "  \"%s\",\n") commands;
6489
6490   pr "  NULL
6491 };
6492
6493 static char *
6494 generator (const char *text, int state)
6495 {
6496   static int index, len;
6497   const char *name;
6498
6499   if (!state) {
6500     index = 0;
6501     len = strlen (text);
6502   }
6503
6504   rl_attempted_completion_over = 1;
6505
6506   while ((name = commands[index]) != NULL) {
6507     index++;
6508     if (strncasecmp (name, text, len) == 0)
6509       return strdup (name);
6510   }
6511
6512   return NULL;
6513 }
6514
6515 #endif /* HAVE_LIBREADLINE */
6516
6517 char **do_completion (const char *text, int start, int end)
6518 {
6519   char **matches = NULL;
6520
6521 #ifdef HAVE_LIBREADLINE
6522   rl_completion_append_character = ' ';
6523
6524   if (start == 0)
6525     matches = rl_completion_matches (text, generator);
6526   else if (complete_dest_paths)
6527     matches = rl_completion_matches (text, complete_dest_paths_generator);
6528 #endif
6529
6530   return matches;
6531 }
6532 ";
6533
6534 (* Generate the POD documentation for guestfish. *)
6535 and generate_fish_actions_pod () =
6536   let all_functions_sorted =
6537     List.filter (
6538       fun (_, _, _, flags, _, _, _) ->
6539         not (List.mem NotInFish flags || List.mem NotInDocs flags)
6540     ) all_functions_sorted in
6541
6542   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
6543
6544   List.iter (
6545     fun (name, style, _, flags, _, _, longdesc) ->
6546       let longdesc =
6547         Str.global_substitute rex (
6548           fun s ->
6549             let sub =
6550               try Str.matched_group 1 s
6551               with Not_found ->
6552                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
6553             "C<" ^ replace_char sub '_' '-' ^ ">"
6554         ) longdesc in
6555       let name = replace_char name '_' '-' in
6556       let alias =
6557         try find_map (function FishAlias n -> Some n | _ -> None) flags
6558         with Not_found -> name in
6559
6560       pr "=head2 %s" name;
6561       if name <> alias then
6562         pr " | %s" alias;
6563       pr "\n";
6564       pr "\n";
6565       pr " %s" name;
6566       List.iter (
6567         function
6568         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
6569         | OptString n -> pr " %s" n
6570         | StringList n | DeviceList n -> pr " '%s ...'" n
6571         | Bool _ -> pr " true|false"
6572         | Int n -> pr " %s" n
6573         | FileIn n | FileOut n -> pr " (%s|-)" n
6574       ) (snd style);
6575       pr "\n";
6576       pr "\n";
6577       pr "%s\n\n" longdesc;
6578
6579       if List.exists (function FileIn _ | FileOut _ -> true
6580                       | _ -> false) (snd style) then
6581         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
6582
6583       if List.mem ProtocolLimitWarning flags then
6584         pr "%s\n\n" protocol_limit_warning;
6585
6586       if List.mem DangerWillRobinson flags then
6587         pr "%s\n\n" danger_will_robinson;
6588
6589       match deprecation_notice flags with
6590       | None -> ()
6591       | Some txt -> pr "%s\n\n" txt
6592   ) all_functions_sorted
6593
6594 (* Generate a C function prototype. *)
6595 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
6596     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
6597     ?(prefix = "")
6598     ?handle name style =
6599   if extern then pr "extern ";
6600   if static then pr "static ";
6601   (match fst style with
6602    | RErr -> pr "int "
6603    | RInt _ -> pr "int "
6604    | RInt64 _ -> pr "int64_t "
6605    | RBool _ -> pr "int "
6606    | RConstString _ | RConstOptString _ -> pr "const char *"
6607    | RString _ | RBufferOut _ -> pr "char *"
6608    | RStringList _ | RHashtable _ -> pr "char **"
6609    | RStruct (_, typ) ->
6610        if not in_daemon then pr "struct guestfs_%s *" typ
6611        else pr "guestfs_int_%s *" typ
6612    | RStructList (_, typ) ->
6613        if not in_daemon then pr "struct guestfs_%s_list *" typ
6614        else pr "guestfs_int_%s_list *" typ
6615   );
6616   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
6617   pr "%s%s (" prefix name;
6618   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
6619     pr "void"
6620   else (
6621     let comma = ref false in
6622     (match handle with
6623      | None -> ()
6624      | Some handle -> pr "guestfs_h *%s" handle; comma := true
6625     );
6626     let next () =
6627       if !comma then (
6628         if single_line then pr ", " else pr ",\n\t\t"
6629       );
6630       comma := true
6631     in
6632     List.iter (
6633       function
6634       | Pathname n
6635       | Device n | Dev_or_Path n
6636       | String n
6637       | OptString n ->
6638           next ();
6639           pr "const char *%s" n
6640       | StringList n | DeviceList n ->
6641           next ();
6642           pr "char *const *%s" n
6643       | Bool n -> next (); pr "int %s" n
6644       | Int n -> next (); pr "int %s" n
6645       | FileIn n
6646       | FileOut n ->
6647           if not in_daemon then (next (); pr "const char *%s" n)
6648     ) (snd style);
6649     if is_RBufferOut then (next (); pr "size_t *size_r");
6650   );
6651   pr ")";
6652   if semicolon then pr ";";
6653   if newline then pr "\n"
6654
6655 (* Generate C call arguments, eg "(handle, foo, bar)" *)
6656 and generate_c_call_args ?handle ?(decl = false) style =
6657   pr "(";
6658   let comma = ref false in
6659   let next () =
6660     if !comma then pr ", ";
6661     comma := true
6662   in
6663   (match handle with
6664    | None -> ()
6665    | Some handle -> pr "%s" handle; comma := true
6666   );
6667   List.iter (
6668     fun arg ->
6669       next ();
6670       pr "%s" (name_of_argt arg)
6671   ) (snd style);
6672   (* For RBufferOut calls, add implicit &size parameter. *)
6673   if not decl then (
6674     match fst style with
6675     | RBufferOut _ ->
6676         next ();
6677         pr "&size"
6678     | _ -> ()
6679   );
6680   pr ")"
6681
6682 (* Generate the OCaml bindings interface. *)
6683 and generate_ocaml_mli () =
6684   generate_header OCamlStyle LGPLv2;
6685
6686   pr "\
6687 (** For API documentation you should refer to the C API
6688     in the guestfs(3) manual page.  The OCaml API uses almost
6689     exactly the same calls. *)
6690
6691 type t
6692 (** A [guestfs_h] handle. *)
6693
6694 exception Error of string
6695 (** This exception is raised when there is an error. *)
6696
6697 val create : unit -> t
6698
6699 val close : t -> unit
6700 (** Handles are closed by the garbage collector when they become
6701     unreferenced, but callers can also call this in order to
6702     provide predictable cleanup. *)
6703
6704 ";
6705   generate_ocaml_structure_decls ();
6706
6707   (* The actions. *)
6708   List.iter (
6709     fun (name, style, _, _, _, shortdesc, _) ->
6710       generate_ocaml_prototype name style;
6711       pr "(** %s *)\n" shortdesc;
6712       pr "\n"
6713   ) all_functions
6714
6715 (* Generate the OCaml bindings implementation. *)
6716 and generate_ocaml_ml () =
6717   generate_header OCamlStyle LGPLv2;
6718
6719   pr "\
6720 type t
6721 exception Error of string
6722 external create : unit -> t = \"ocaml_guestfs_create\"
6723 external close : t -> unit = \"ocaml_guestfs_close\"
6724
6725 let () =
6726   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\")
6727
6728 ";
6729
6730   generate_ocaml_structure_decls ();
6731
6732   (* The actions. *)
6733   List.iter (
6734     fun (name, style, _, _, _, shortdesc, _) ->
6735       generate_ocaml_prototype ~is_external:true name style;
6736   ) all_functions
6737
6738 (* Generate the OCaml bindings C implementation. *)
6739 and generate_ocaml_c () =
6740   generate_header CStyle LGPLv2;
6741
6742   pr "\
6743 #include <stdio.h>
6744 #include <stdlib.h>
6745 #include <string.h>
6746
6747 #include <caml/config.h>
6748 #include <caml/alloc.h>
6749 #include <caml/callback.h>
6750 #include <caml/fail.h>
6751 #include <caml/memory.h>
6752 #include <caml/mlvalues.h>
6753 #include <caml/signals.h>
6754
6755 #include <guestfs.h>
6756
6757 #include \"guestfs_c.h\"
6758
6759 /* Copy a hashtable of string pairs into an assoc-list.  We return
6760  * the list in reverse order, but hashtables aren't supposed to be
6761  * ordered anyway.
6762  */
6763 static CAMLprim value
6764 copy_table (char * const * argv)
6765 {
6766   CAMLparam0 ();
6767   CAMLlocal5 (rv, pairv, kv, vv, cons);
6768   int i;
6769
6770   rv = Val_int (0);
6771   for (i = 0; argv[i] != NULL; i += 2) {
6772     kv = caml_copy_string (argv[i]);
6773     vv = caml_copy_string (argv[i+1]);
6774     pairv = caml_alloc (2, 0);
6775     Store_field (pairv, 0, kv);
6776     Store_field (pairv, 1, vv);
6777     cons = caml_alloc (2, 0);
6778     Store_field (cons, 1, rv);
6779     rv = cons;
6780     Store_field (cons, 0, pairv);
6781   }
6782
6783   CAMLreturn (rv);
6784 }
6785
6786 ";
6787
6788   (* Struct copy functions. *)
6789
6790   let emit_ocaml_copy_list_function typ =
6791     pr "static CAMLprim value\n";
6792     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
6793     pr "{\n";
6794     pr "  CAMLparam0 ();\n";
6795     pr "  CAMLlocal2 (rv, v);\n";
6796     pr "  unsigned int i;\n";
6797     pr "\n";
6798     pr "  if (%ss->len == 0)\n" typ;
6799     pr "    CAMLreturn (Atom (0));\n";
6800     pr "  else {\n";
6801     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
6802     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
6803     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
6804     pr "      caml_modify (&Field (rv, i), v);\n";
6805     pr "    }\n";
6806     pr "    CAMLreturn (rv);\n";
6807     pr "  }\n";
6808     pr "}\n";
6809     pr "\n";
6810   in
6811
6812   List.iter (
6813     fun (typ, cols) ->
6814       let has_optpercent_col =
6815         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
6816
6817       pr "static CAMLprim value\n";
6818       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
6819       pr "{\n";
6820       pr "  CAMLparam0 ();\n";
6821       if has_optpercent_col then
6822         pr "  CAMLlocal3 (rv, v, v2);\n"
6823       else
6824         pr "  CAMLlocal2 (rv, v);\n";
6825       pr "\n";
6826       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
6827       iteri (
6828         fun i col ->
6829           (match col with
6830            | name, FString ->
6831                pr "  v = caml_copy_string (%s->%s);\n" typ name
6832            | name, FBuffer ->
6833                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
6834                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
6835                  typ name typ name
6836            | name, FUUID ->
6837                pr "  v = caml_alloc_string (32);\n";
6838                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
6839            | name, (FBytes|FInt64|FUInt64) ->
6840                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
6841            | name, (FInt32|FUInt32) ->
6842                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
6843            | name, FOptPercent ->
6844                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
6845                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
6846                pr "    v = caml_alloc (1, 0);\n";
6847                pr "    Store_field (v, 0, v2);\n";
6848                pr "  } else /* None */\n";
6849                pr "    v = Val_int (0);\n";
6850            | name, FChar ->
6851                pr "  v = Val_int (%s->%s);\n" typ name
6852           );
6853           pr "  Store_field (rv, %d, v);\n" i
6854       ) cols;
6855       pr "  CAMLreturn (rv);\n";
6856       pr "}\n";
6857       pr "\n";
6858   ) structs;
6859
6860   (* Emit a copy_TYPE_list function definition only if that function is used. *)
6861   List.iter (
6862     function
6863     | typ, (RStructListOnly | RStructAndList) ->
6864         (* generate the function for typ *)
6865         emit_ocaml_copy_list_function typ
6866     | typ, _ -> () (* empty *)
6867   ) rstructs_used;
6868
6869   (* The wrappers. *)
6870   List.iter (
6871     fun (name, style, _, _, _, _, _) ->
6872       let params =
6873         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
6874
6875       let needs_extra_vs =
6876         match fst style with RConstOptString _ -> true | _ -> false in
6877
6878       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
6879       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
6880       List.iter (pr ", value %s") (List.tl params); pr ");\n";
6881
6882       pr "CAMLprim value\n";
6883       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
6884       List.iter (pr ", value %s") (List.tl params);
6885       pr ")\n";
6886       pr "{\n";
6887
6888       (match params with
6889        | [p1; p2; p3; p4; p5] ->
6890            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
6891        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
6892            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
6893            pr "  CAMLxparam%d (%s);\n"
6894              (List.length rest) (String.concat ", " rest)
6895        | ps ->
6896            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
6897       );
6898       if not needs_extra_vs then
6899         pr "  CAMLlocal1 (rv);\n"
6900       else
6901         pr "  CAMLlocal3 (rv, v, v2);\n";
6902       pr "\n";
6903
6904       pr "  guestfs_h *g = Guestfs_val (gv);\n";
6905       pr "  if (g == NULL)\n";
6906       pr "    caml_failwith (\"%s: used handle after closing it\");\n" name;
6907       pr "\n";
6908
6909       List.iter (
6910         function
6911         | Pathname n
6912         | Device n | Dev_or_Path n
6913         | String n
6914         | FileIn n
6915         | FileOut n ->
6916             pr "  const char *%s = String_val (%sv);\n" n n
6917         | OptString n ->
6918             pr "  const char *%s =\n" n;
6919             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
6920               n n
6921         | StringList n | DeviceList n ->
6922             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
6923         | Bool n ->
6924             pr "  int %s = Bool_val (%sv);\n" n n
6925         | Int n ->
6926             pr "  int %s = Int_val (%sv);\n" n n
6927       ) (snd style);
6928       let error_code =
6929         match fst style with
6930         | RErr -> pr "  int r;\n"; "-1"
6931         | RInt _ -> pr "  int r;\n"; "-1"
6932         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6933         | RBool _ -> pr "  int r;\n"; "-1"
6934         | RConstString _ | RConstOptString _ ->
6935             pr "  const char *r;\n"; "NULL"
6936         | RString _ -> pr "  char *r;\n"; "NULL"
6937         | RStringList _ ->
6938             pr "  int i;\n";
6939             pr "  char **r;\n";
6940             "NULL"
6941         | RStruct (_, typ) ->
6942             pr "  struct guestfs_%s *r;\n" typ; "NULL"
6943         | RStructList (_, typ) ->
6944             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
6945         | RHashtable _ ->
6946             pr "  int i;\n";
6947             pr "  char **r;\n";
6948             "NULL"
6949         | RBufferOut _ ->
6950             pr "  char *r;\n";
6951             pr "  size_t size;\n";
6952             "NULL" in
6953       pr "\n";
6954
6955       pr "  caml_enter_blocking_section ();\n";
6956       pr "  r = guestfs_%s " name;
6957       generate_c_call_args ~handle:"g" style;
6958       pr ";\n";
6959       pr "  caml_leave_blocking_section ();\n";
6960
6961       List.iter (
6962         function
6963         | StringList n | DeviceList n ->
6964             pr "  ocaml_guestfs_free_strings (%s);\n" n;
6965         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
6966         | FileIn _ | FileOut _ -> ()
6967       ) (snd style);
6968
6969       pr "  if (r == %s)\n" error_code;
6970       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
6971       pr "\n";
6972
6973       (match fst style with
6974        | RErr -> pr "  rv = Val_unit;\n"
6975        | RInt _ -> pr "  rv = Val_int (r);\n"
6976        | RInt64 _ ->
6977            pr "  rv = caml_copy_int64 (r);\n"
6978        | RBool _ -> pr "  rv = Val_bool (r);\n"
6979        | RConstString _ ->
6980            pr "  rv = caml_copy_string (r);\n"
6981        | RConstOptString _ ->
6982            pr "  if (r) { /* Some string */\n";
6983            pr "    v = caml_alloc (1, 0);\n";
6984            pr "    v2 = caml_copy_string (r);\n";
6985            pr "    Store_field (v, 0, v2);\n";
6986            pr "  } else /* None */\n";
6987            pr "    v = Val_int (0);\n";
6988        | RString _ ->
6989            pr "  rv = caml_copy_string (r);\n";
6990            pr "  free (r);\n"
6991        | RStringList _ ->
6992            pr "  rv = caml_copy_string_array ((const char **) r);\n";
6993            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
6994            pr "  free (r);\n"
6995        | RStruct (_, typ) ->
6996            pr "  rv = copy_%s (r);\n" typ;
6997            pr "  guestfs_free_%s (r);\n" typ;
6998        | RStructList (_, typ) ->
6999            pr "  rv = copy_%s_list (r);\n" typ;
7000            pr "  guestfs_free_%s_list (r);\n" typ;
7001        | RHashtable _ ->
7002            pr "  rv = copy_table (r);\n";
7003            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7004            pr "  free (r);\n";
7005        | RBufferOut _ ->
7006            pr "  rv = caml_alloc_string (size);\n";
7007            pr "  memcpy (String_val (rv), r, size);\n";
7008       );
7009
7010       pr "  CAMLreturn (rv);\n";
7011       pr "}\n";
7012       pr "\n";
7013
7014       if List.length params > 5 then (
7015         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7016         pr "CAMLprim value ";
7017         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7018         pr "CAMLprim value\n";
7019         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7020         pr "{\n";
7021         pr "  return ocaml_guestfs_%s (argv[0]" name;
7022         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7023         pr ");\n";
7024         pr "}\n";
7025         pr "\n"
7026       )
7027   ) all_functions
7028
7029 and generate_ocaml_structure_decls () =
7030   List.iter (
7031     fun (typ, cols) ->
7032       pr "type %s = {\n" typ;
7033       List.iter (
7034         function
7035         | name, FString -> pr "  %s : string;\n" name
7036         | name, FBuffer -> pr "  %s : string;\n" name
7037         | name, FUUID -> pr "  %s : string;\n" name
7038         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7039         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7040         | name, FChar -> pr "  %s : char;\n" name
7041         | name, FOptPercent -> pr "  %s : float option;\n" name
7042       ) cols;
7043       pr "}\n";
7044       pr "\n"
7045   ) structs
7046
7047 and generate_ocaml_prototype ?(is_external = false) name style =
7048   if is_external then pr "external " else pr "val ";
7049   pr "%s : t -> " name;
7050   List.iter (
7051     function
7052     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7053     | OptString _ -> pr "string option -> "
7054     | StringList _ | DeviceList _ -> pr "string array -> "
7055     | Bool _ -> pr "bool -> "
7056     | Int _ -> pr "int -> "
7057   ) (snd style);
7058   (match fst style with
7059    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7060    | RInt _ -> pr "int"
7061    | RInt64 _ -> pr "int64"
7062    | RBool _ -> pr "bool"
7063    | RConstString _ -> pr "string"
7064    | RConstOptString _ -> pr "string option"
7065    | RString _ | RBufferOut _ -> pr "string"
7066    | RStringList _ -> pr "string array"
7067    | RStruct (_, typ) -> pr "%s" typ
7068    | RStructList (_, typ) -> pr "%s array" typ
7069    | RHashtable _ -> pr "(string * string) list"
7070   );
7071   if is_external then (
7072     pr " = ";
7073     if List.length (snd style) + 1 > 5 then
7074       pr "\"ocaml_guestfs_%s_byte\" " name;
7075     pr "\"ocaml_guestfs_%s\"" name
7076   );
7077   pr "\n"
7078
7079 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7080 and generate_perl_xs () =
7081   generate_header CStyle LGPLv2;
7082
7083   pr "\
7084 #include \"EXTERN.h\"
7085 #include \"perl.h\"
7086 #include \"XSUB.h\"
7087
7088 #include <guestfs.h>
7089
7090 #ifndef PRId64
7091 #define PRId64 \"lld\"
7092 #endif
7093
7094 static SV *
7095 my_newSVll(long long val) {
7096 #ifdef USE_64_BIT_ALL
7097   return newSViv(val);
7098 #else
7099   char buf[100];
7100   int len;
7101   len = snprintf(buf, 100, \"%%\" PRId64, val);
7102   return newSVpv(buf, len);
7103 #endif
7104 }
7105
7106 #ifndef PRIu64
7107 #define PRIu64 \"llu\"
7108 #endif
7109
7110 static SV *
7111 my_newSVull(unsigned long long val) {
7112 #ifdef USE_64_BIT_ALL
7113   return newSVuv(val);
7114 #else
7115   char buf[100];
7116   int len;
7117   len = snprintf(buf, 100, \"%%\" PRIu64, val);
7118   return newSVpv(buf, len);
7119 #endif
7120 }
7121
7122 /* http://www.perlmonks.org/?node_id=680842 */
7123 static char **
7124 XS_unpack_charPtrPtr (SV *arg) {
7125   char **ret;
7126   AV *av;
7127   I32 i;
7128
7129   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
7130     croak (\"array reference expected\");
7131
7132   av = (AV *)SvRV (arg);
7133   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
7134   if (!ret)
7135     croak (\"malloc failed\");
7136
7137   for (i = 0; i <= av_len (av); i++) {
7138     SV **elem = av_fetch (av, i, 0);
7139
7140     if (!elem || !*elem)
7141       croak (\"missing element in list\");
7142
7143     ret[i] = SvPV_nolen (*elem);
7144   }
7145
7146   ret[i] = NULL;
7147
7148   return ret;
7149 }
7150
7151 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
7152
7153 PROTOTYPES: ENABLE
7154
7155 guestfs_h *
7156 _create ()
7157    CODE:
7158       RETVAL = guestfs_create ();
7159       if (!RETVAL)
7160         croak (\"could not create guestfs handle\");
7161       guestfs_set_error_handler (RETVAL, NULL, NULL);
7162  OUTPUT:
7163       RETVAL
7164
7165 void
7166 DESTROY (g)
7167       guestfs_h *g;
7168  PPCODE:
7169       guestfs_close (g);
7170
7171 ";
7172
7173   List.iter (
7174     fun (name, style, _, _, _, _, _) ->
7175       (match fst style with
7176        | RErr -> pr "void\n"
7177        | RInt _ -> pr "SV *\n"
7178        | RInt64 _ -> pr "SV *\n"
7179        | RBool _ -> pr "SV *\n"
7180        | RConstString _ -> pr "SV *\n"
7181        | RConstOptString _ -> pr "SV *\n"
7182        | RString _ -> pr "SV *\n"
7183        | RBufferOut _ -> pr "SV *\n"
7184        | RStringList _
7185        | RStruct _ | RStructList _
7186        | RHashtable _ ->
7187            pr "void\n" (* all lists returned implictly on the stack *)
7188       );
7189       (* Call and arguments. *)
7190       pr "%s " name;
7191       generate_c_call_args ~handle:"g" ~decl:true style;
7192       pr "\n";
7193       pr "      guestfs_h *g;\n";
7194       iteri (
7195         fun i ->
7196           function
7197           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7198               pr "      char *%s;\n" n
7199           | OptString n ->
7200               (* http://www.perlmonks.org/?node_id=554277
7201                * Note that the implicit handle argument means we have
7202                * to add 1 to the ST(x) operator.
7203                *)
7204               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
7205           | StringList n | DeviceList n -> pr "      char **%s;\n" n
7206           | Bool n -> pr "      int %s;\n" n
7207           | Int n -> pr "      int %s;\n" n
7208       ) (snd style);
7209
7210       let do_cleanups () =
7211         List.iter (
7212           function
7213           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _ | Bool _ | Int _
7214           | FileIn _ | FileOut _ -> ()
7215           | StringList n | DeviceList n -> pr "      free (%s);\n" n
7216         ) (snd style)
7217       in
7218
7219       (* Code. *)
7220       (match fst style with
7221        | RErr ->
7222            pr "PREINIT:\n";
7223            pr "      int r;\n";
7224            pr " PPCODE:\n";
7225            pr "      r = guestfs_%s " name;
7226            generate_c_call_args ~handle:"g" style;
7227            pr ";\n";
7228            do_cleanups ();
7229            pr "      if (r == -1)\n";
7230            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7231        | RInt n
7232        | RBool n ->
7233            pr "PREINIT:\n";
7234            pr "      int %s;\n" n;
7235            pr "   CODE:\n";
7236            pr "      %s = guestfs_%s " n name;
7237            generate_c_call_args ~handle:"g" style;
7238            pr ";\n";
7239            do_cleanups ();
7240            pr "      if (%s == -1)\n" n;
7241            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7242            pr "      RETVAL = newSViv (%s);\n" n;
7243            pr " OUTPUT:\n";
7244            pr "      RETVAL\n"
7245        | RInt64 n ->
7246            pr "PREINIT:\n";
7247            pr "      int64_t %s;\n" n;
7248            pr "   CODE:\n";
7249            pr "      %s = guestfs_%s " n name;
7250            generate_c_call_args ~handle:"g" style;
7251            pr ";\n";
7252            do_cleanups ();
7253            pr "      if (%s == -1)\n" n;
7254            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7255            pr "      RETVAL = my_newSVll (%s);\n" n;
7256            pr " OUTPUT:\n";
7257            pr "      RETVAL\n"
7258        | RConstString n ->
7259            pr "PREINIT:\n";
7260            pr "      const char *%s;\n" n;
7261            pr "   CODE:\n";
7262            pr "      %s = guestfs_%s " n name;
7263            generate_c_call_args ~handle:"g" style;
7264            pr ";\n";
7265            do_cleanups ();
7266            pr "      if (%s == NULL)\n" n;
7267            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7268            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7269            pr " OUTPUT:\n";
7270            pr "      RETVAL\n"
7271        | RConstOptString n ->
7272            pr "PREINIT:\n";
7273            pr "      const char *%s;\n" n;
7274            pr "   CODE:\n";
7275            pr "      %s = guestfs_%s " n name;
7276            generate_c_call_args ~handle:"g" style;
7277            pr ";\n";
7278            do_cleanups ();
7279            pr "      if (%s == NULL)\n" n;
7280            pr "        RETVAL = &PL_sv_undef;\n";
7281            pr "      else\n";
7282            pr "        RETVAL = newSVpv (%s, 0);\n" n;
7283            pr " OUTPUT:\n";
7284            pr "      RETVAL\n"
7285        | RString n ->
7286            pr "PREINIT:\n";
7287            pr "      char *%s;\n" n;
7288            pr "   CODE:\n";
7289            pr "      %s = guestfs_%s " n name;
7290            generate_c_call_args ~handle:"g" style;
7291            pr ";\n";
7292            do_cleanups ();
7293            pr "      if (%s == NULL)\n" n;
7294            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7295            pr "      RETVAL = newSVpv (%s, 0);\n" n;
7296            pr "      free (%s);\n" n;
7297            pr " OUTPUT:\n";
7298            pr "      RETVAL\n"
7299        | RStringList n | RHashtable n ->
7300            pr "PREINIT:\n";
7301            pr "      char **%s;\n" n;
7302            pr "      int i, n;\n";
7303            pr " PPCODE:\n";
7304            pr "      %s = guestfs_%s " n name;
7305            generate_c_call_args ~handle:"g" style;
7306            pr ";\n";
7307            do_cleanups ();
7308            pr "      if (%s == NULL)\n" n;
7309            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7310            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
7311            pr "      EXTEND (SP, n);\n";
7312            pr "      for (i = 0; i < n; ++i) {\n";
7313            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
7314            pr "        free (%s[i]);\n" n;
7315            pr "      }\n";
7316            pr "      free (%s);\n" n;
7317        | RStruct (n, typ) ->
7318            let cols = cols_of_struct typ in
7319            generate_perl_struct_code typ cols name style n do_cleanups
7320        | RStructList (n, typ) ->
7321            let cols = cols_of_struct typ in
7322            generate_perl_struct_list_code typ cols name style n do_cleanups
7323        | RBufferOut n ->
7324            pr "PREINIT:\n";
7325            pr "      char *%s;\n" n;
7326            pr "      size_t size;\n";
7327            pr "   CODE:\n";
7328            pr "      %s = guestfs_%s " n name;
7329            generate_c_call_args ~handle:"g" style;
7330            pr ";\n";
7331            do_cleanups ();
7332            pr "      if (%s == NULL)\n" n;
7333            pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7334            pr "      RETVAL = newSVpv (%s, size);\n" n;
7335            pr "      free (%s);\n" n;
7336            pr " OUTPUT:\n";
7337            pr "      RETVAL\n"
7338       );
7339
7340       pr "\n"
7341   ) all_functions
7342
7343 and generate_perl_struct_list_code typ cols name style n do_cleanups =
7344   pr "PREINIT:\n";
7345   pr "      struct guestfs_%s_list *%s;\n" typ n;
7346   pr "      int i;\n";
7347   pr "      HV *hv;\n";
7348   pr " PPCODE:\n";
7349   pr "      %s = guestfs_%s " n name;
7350   generate_c_call_args ~handle:"g" style;
7351   pr ";\n";
7352   do_cleanups ();
7353   pr "      if (%s == NULL)\n" n;
7354   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7355   pr "      EXTEND (SP, %s->len);\n" n;
7356   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
7357   pr "        hv = newHV ();\n";
7358   List.iter (
7359     function
7360     | name, FString ->
7361         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
7362           name (String.length name) n name
7363     | name, FUUID ->
7364         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
7365           name (String.length name) n name
7366     | name, FBuffer ->
7367         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
7368           name (String.length name) n name n name
7369     | name, (FBytes|FUInt64) ->
7370         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
7371           name (String.length name) n name
7372     | name, FInt64 ->
7373         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
7374           name (String.length name) n name
7375     | name, (FInt32|FUInt32) ->
7376         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7377           name (String.length name) n name
7378     | name, FChar ->
7379         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
7380           name (String.length name) n name
7381     | name, FOptPercent ->
7382         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
7383           name (String.length name) n name
7384   ) cols;
7385   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
7386   pr "      }\n";
7387   pr "      guestfs_free_%s_list (%s);\n" typ n
7388
7389 and generate_perl_struct_code typ cols name style n do_cleanups =
7390   pr "PREINIT:\n";
7391   pr "      struct guestfs_%s *%s;\n" typ n;
7392   pr " PPCODE:\n";
7393   pr "      %s = guestfs_%s " n name;
7394   generate_c_call_args ~handle:"g" style;
7395   pr ";\n";
7396   do_cleanups ();
7397   pr "      if (%s == NULL)\n" n;
7398   pr "        croak (\"%s: %%s\", guestfs_last_error (g));\n" name;
7399   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
7400   List.iter (
7401     fun ((name, _) as col) ->
7402       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
7403
7404       match col with
7405       | name, FString ->
7406           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
7407             n name
7408       | name, FBuffer ->
7409           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
7410             n name n name
7411       | name, FUUID ->
7412           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
7413             n name
7414       | name, (FBytes|FUInt64) ->
7415           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
7416             n name
7417       | name, FInt64 ->
7418           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
7419             n name
7420       | name, (FInt32|FUInt32) ->
7421           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7422             n name
7423       | name, FChar ->
7424           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
7425             n name
7426       | name, FOptPercent ->
7427           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
7428             n name
7429   ) cols;
7430   pr "      free (%s);\n" n
7431
7432 (* Generate Sys/Guestfs.pm. *)
7433 and generate_perl_pm () =
7434   generate_header HashStyle LGPLv2;
7435
7436   pr "\
7437 =pod
7438
7439 =head1 NAME
7440
7441 Sys::Guestfs - Perl bindings for libguestfs
7442
7443 =head1 SYNOPSIS
7444
7445  use Sys::Guestfs;
7446
7447  my $h = Sys::Guestfs->new ();
7448  $h->add_drive ('guest.img');
7449  $h->launch ();
7450  $h->mount ('/dev/sda1', '/');
7451  $h->touch ('/hello');
7452  $h->sync ();
7453
7454 =head1 DESCRIPTION
7455
7456 The C<Sys::Guestfs> module provides a Perl XS binding to the
7457 libguestfs API for examining and modifying virtual machine
7458 disk images.
7459
7460 Amongst the things this is good for: making batch configuration
7461 changes to guests, getting disk used/free statistics (see also:
7462 virt-df), migrating between virtualization systems (see also:
7463 virt-p2v), performing partial backups, performing partial guest
7464 clones, cloning guests and changing registry/UUID/hostname info, and
7465 much else besides.
7466
7467 Libguestfs uses Linux kernel and qemu code, and can access any type of
7468 guest filesystem that Linux and qemu can, including but not limited
7469 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
7470 schemes, qcow, qcow2, vmdk.
7471
7472 Libguestfs provides ways to enumerate guest storage (eg. partitions,
7473 LVs, what filesystem is in each LV, etc.).  It can also run commands
7474 in the context of the guest.  Also you can access filesystems over FTP.
7475
7476 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
7477 functions for using libguestfs from Perl, including integration
7478 with libvirt.
7479
7480 =head1 ERRORS
7481
7482 All errors turn into calls to C<croak> (see L<Carp(3)>).
7483
7484 =head1 METHODS
7485
7486 =over 4
7487
7488 =cut
7489
7490 package Sys::Guestfs;
7491
7492 use strict;
7493 use warnings;
7494
7495 require XSLoader;
7496 XSLoader::load ('Sys::Guestfs');
7497
7498 =item $h = Sys::Guestfs->new ();
7499
7500 Create a new guestfs handle.
7501
7502 =cut
7503
7504 sub new {
7505   my $proto = shift;
7506   my $class = ref ($proto) || $proto;
7507
7508   my $self = Sys::Guestfs::_create ();
7509   bless $self, $class;
7510   return $self;
7511 }
7512
7513 ";
7514
7515   (* Actions.  We only need to print documentation for these as
7516    * they are pulled in from the XS code automatically.
7517    *)
7518   List.iter (
7519     fun (name, style, _, flags, _, _, longdesc) ->
7520       if not (List.mem NotInDocs flags) then (
7521         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
7522         pr "=item ";
7523         generate_perl_prototype name style;
7524         pr "\n\n";
7525         pr "%s\n\n" longdesc;
7526         if List.mem ProtocolLimitWarning flags then
7527           pr "%s\n\n" protocol_limit_warning;
7528         if List.mem DangerWillRobinson flags then
7529           pr "%s\n\n" danger_will_robinson;
7530         match deprecation_notice flags with
7531         | None -> ()
7532         | Some txt -> pr "%s\n\n" txt
7533       )
7534   ) all_functions_sorted;
7535
7536   (* End of file. *)
7537   pr "\
7538 =cut
7539
7540 1;
7541
7542 =back
7543
7544 =head1 COPYRIGHT
7545
7546 Copyright (C) 2009 Red Hat Inc.
7547
7548 =head1 LICENSE
7549
7550 Please see the file COPYING.LIB for the full license.
7551
7552 =head1 SEE ALSO
7553
7554 L<guestfs(3)>,
7555 L<guestfish(1)>,
7556 L<http://libguestfs.org>,
7557 L<Sys::Guestfs::Lib(3)>.
7558
7559 =cut
7560 "
7561
7562 and generate_perl_prototype name style =
7563   (match fst style with
7564    | RErr -> ()
7565    | RBool n
7566    | RInt n
7567    | RInt64 n
7568    | RConstString n
7569    | RConstOptString n
7570    | RString n
7571    | RBufferOut n -> pr "$%s = " n
7572    | RStruct (n,_)
7573    | RHashtable n -> pr "%%%s = " n
7574    | RStringList n
7575    | RStructList (n,_) -> pr "@%s = " n
7576   );
7577   pr "$h->%s (" name;
7578   let comma = ref false in
7579   List.iter (
7580     fun arg ->
7581       if !comma then pr ", ";
7582       comma := true;
7583       match arg with
7584       | Pathname n | Device n | Dev_or_Path n | String n
7585       | OptString n | Bool n | Int n | FileIn n | FileOut n ->
7586           pr "$%s" n
7587       | StringList n | DeviceList n ->
7588           pr "\\@%s" n
7589   ) (snd style);
7590   pr ");"
7591
7592 (* Generate Python C module. *)
7593 and generate_python_c () =
7594   generate_header CStyle LGPLv2;
7595
7596   pr "\
7597 #include <Python.h>
7598
7599 #include <stdio.h>
7600 #include <stdlib.h>
7601 #include <assert.h>
7602
7603 #include \"guestfs.h\"
7604
7605 typedef struct {
7606   PyObject_HEAD
7607   guestfs_h *g;
7608 } Pyguestfs_Object;
7609
7610 static guestfs_h *
7611 get_handle (PyObject *obj)
7612 {
7613   assert (obj);
7614   assert (obj != Py_None);
7615   return ((Pyguestfs_Object *) obj)->g;
7616 }
7617
7618 static PyObject *
7619 put_handle (guestfs_h *g)
7620 {
7621   assert (g);
7622   return
7623     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
7624 }
7625
7626 /* This list should be freed (but not the strings) after use. */
7627 static char **
7628 get_string_list (PyObject *obj)
7629 {
7630   int i, len;
7631   char **r;
7632
7633   assert (obj);
7634
7635   if (!PyList_Check (obj)) {
7636     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
7637     return NULL;
7638   }
7639
7640   len = PyList_Size (obj);
7641   r = malloc (sizeof (char *) * (len+1));
7642   if (r == NULL) {
7643     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
7644     return NULL;
7645   }
7646
7647   for (i = 0; i < len; ++i)
7648     r[i] = PyString_AsString (PyList_GetItem (obj, i));
7649   r[len] = NULL;
7650
7651   return r;
7652 }
7653
7654 static PyObject *
7655 put_string_list (char * const * const argv)
7656 {
7657   PyObject *list;
7658   int argc, i;
7659
7660   for (argc = 0; argv[argc] != NULL; ++argc)
7661     ;
7662
7663   list = PyList_New (argc);
7664   for (i = 0; i < argc; ++i)
7665     PyList_SetItem (list, i, PyString_FromString (argv[i]));
7666
7667   return list;
7668 }
7669
7670 static PyObject *
7671 put_table (char * const * const argv)
7672 {
7673   PyObject *list, *item;
7674   int argc, i;
7675
7676   for (argc = 0; argv[argc] != NULL; ++argc)
7677     ;
7678
7679   list = PyList_New (argc >> 1);
7680   for (i = 0; i < argc; i += 2) {
7681     item = PyTuple_New (2);
7682     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
7683     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
7684     PyList_SetItem (list, i >> 1, item);
7685   }
7686
7687   return list;
7688 }
7689
7690 static void
7691 free_strings (char **argv)
7692 {
7693   int argc;
7694
7695   for (argc = 0; argv[argc] != NULL; ++argc)
7696     free (argv[argc]);
7697   free (argv);
7698 }
7699
7700 static PyObject *
7701 py_guestfs_create (PyObject *self, PyObject *args)
7702 {
7703   guestfs_h *g;
7704
7705   g = guestfs_create ();
7706   if (g == NULL) {
7707     PyErr_SetString (PyExc_RuntimeError,
7708                      \"guestfs.create: failed to allocate handle\");
7709     return NULL;
7710   }
7711   guestfs_set_error_handler (g, NULL, NULL);
7712   return put_handle (g);
7713 }
7714
7715 static PyObject *
7716 py_guestfs_close (PyObject *self, PyObject *args)
7717 {
7718   PyObject *py_g;
7719   guestfs_h *g;
7720
7721   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
7722     return NULL;
7723   g = get_handle (py_g);
7724
7725   guestfs_close (g);
7726
7727   Py_INCREF (Py_None);
7728   return Py_None;
7729 }
7730
7731 ";
7732
7733   let emit_put_list_function typ =
7734     pr "static PyObject *\n";
7735     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
7736     pr "{\n";
7737     pr "  PyObject *list;\n";
7738     pr "  int i;\n";
7739     pr "\n";
7740     pr "  list = PyList_New (%ss->len);\n" typ;
7741     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
7742     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
7743     pr "  return list;\n";
7744     pr "};\n";
7745     pr "\n"
7746   in
7747
7748   (* Structures, turned into Python dictionaries. *)
7749   List.iter (
7750     fun (typ, cols) ->
7751       pr "static PyObject *\n";
7752       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
7753       pr "{\n";
7754       pr "  PyObject *dict;\n";
7755       pr "\n";
7756       pr "  dict = PyDict_New ();\n";
7757       List.iter (
7758         function
7759         | name, FString ->
7760             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7761             pr "                        PyString_FromString (%s->%s));\n"
7762               typ name
7763         | name, FBuffer ->
7764             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7765             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
7766               typ name typ name
7767         | name, FUUID ->
7768             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7769             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
7770               typ name
7771         | name, (FBytes|FUInt64) ->
7772             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7773             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
7774               typ name
7775         | name, FInt64 ->
7776             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7777             pr "                        PyLong_FromLongLong (%s->%s));\n"
7778               typ name
7779         | name, FUInt32 ->
7780             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7781             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
7782               typ name
7783         | name, FInt32 ->
7784             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7785             pr "                        PyLong_FromLong (%s->%s));\n"
7786               typ name
7787         | name, FOptPercent ->
7788             pr "  if (%s->%s >= 0)\n" typ name;
7789             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
7790             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
7791               typ name;
7792             pr "  else {\n";
7793             pr "    Py_INCREF (Py_None);\n";
7794             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
7795             pr "  }\n"
7796         | name, FChar ->
7797             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
7798             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
7799       ) cols;
7800       pr "  return dict;\n";
7801       pr "};\n";
7802       pr "\n";
7803
7804   ) structs;
7805
7806   (* Emit a put_TYPE_list function definition only if that function is used. *)
7807   List.iter (
7808     function
7809     | typ, (RStructListOnly | RStructAndList) ->
7810         (* generate the function for typ *)
7811         emit_put_list_function typ
7812     | typ, _ -> () (* empty *)
7813   ) rstructs_used;
7814
7815   (* Python wrapper functions. *)
7816   List.iter (
7817     fun (name, style, _, _, _, _, _) ->
7818       pr "static PyObject *\n";
7819       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
7820       pr "{\n";
7821
7822       pr "  PyObject *py_g;\n";
7823       pr "  guestfs_h *g;\n";
7824       pr "  PyObject *py_r;\n";
7825
7826       let error_code =
7827         match fst style with
7828         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
7829         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7830         | RConstString _ | RConstOptString _ ->
7831             pr "  const char *r;\n"; "NULL"
7832         | RString _ -> pr "  char *r;\n"; "NULL"
7833         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
7834         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
7835         | RStructList (_, typ) ->
7836             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7837         | RBufferOut _ ->
7838             pr "  char *r;\n";
7839             pr "  size_t size;\n";
7840             "NULL" in
7841
7842       List.iter (
7843         function
7844         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
7845             pr "  const char *%s;\n" n
7846         | OptString n -> pr "  const char *%s;\n" n
7847         | StringList n | DeviceList n ->
7848             pr "  PyObject *py_%s;\n" n;
7849             pr "  char **%s;\n" n
7850         | Bool n -> pr "  int %s;\n" n
7851         | Int n -> pr "  int %s;\n" n
7852       ) (snd style);
7853
7854       pr "\n";
7855
7856       (* Convert the parameters. *)
7857       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
7858       List.iter (
7859         function
7860         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
7861         | OptString _ -> pr "z"
7862         | StringList _ | DeviceList _ -> pr "O"
7863         | Bool _ -> pr "i" (* XXX Python has booleans? *)
7864         | Int _ -> pr "i"
7865       ) (snd style);
7866       pr ":guestfs_%s\",\n" name;
7867       pr "                         &py_g";
7868       List.iter (
7869         function
7870         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
7871         | OptString n -> pr ", &%s" n
7872         | StringList n | DeviceList n -> pr ", &py_%s" n
7873         | Bool n -> pr ", &%s" n
7874         | Int n -> pr ", &%s" n
7875       ) (snd style);
7876
7877       pr "))\n";
7878       pr "    return NULL;\n";
7879
7880       pr "  g = get_handle (py_g);\n";
7881       List.iter (
7882         function
7883         | Pathname _ | Device _ | Dev_or_Path _ | String _
7884         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7885         | StringList n | DeviceList n ->
7886             pr "  %s = get_string_list (py_%s);\n" n n;
7887             pr "  if (!%s) return NULL;\n" n
7888       ) (snd style);
7889
7890       pr "\n";
7891
7892       pr "  r = guestfs_%s " name;
7893       generate_c_call_args ~handle:"g" style;
7894       pr ";\n";
7895
7896       List.iter (
7897         function
7898         | Pathname _ | Device _ | Dev_or_Path _ | String _
7899         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
7900         | StringList n | DeviceList n ->
7901             pr "  free (%s);\n" n
7902       ) (snd style);
7903
7904       pr "  if (r == %s) {\n" error_code;
7905       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
7906       pr "    return NULL;\n";
7907       pr "  }\n";
7908       pr "\n";
7909
7910       (match fst style with
7911        | RErr ->
7912            pr "  Py_INCREF (Py_None);\n";
7913            pr "  py_r = Py_None;\n"
7914        | RInt _
7915        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
7916        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
7917        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
7918        | RConstOptString _ ->
7919            pr "  if (r)\n";
7920            pr "    py_r = PyString_FromString (r);\n";
7921            pr "  else {\n";
7922            pr "    Py_INCREF (Py_None);\n";
7923            pr "    py_r = Py_None;\n";
7924            pr "  }\n"
7925        | RString _ ->
7926            pr "  py_r = PyString_FromString (r);\n";
7927            pr "  free (r);\n"
7928        | RStringList _ ->
7929            pr "  py_r = put_string_list (r);\n";
7930            pr "  free_strings (r);\n"
7931        | RStruct (_, typ) ->
7932            pr "  py_r = put_%s (r);\n" typ;
7933            pr "  guestfs_free_%s (r);\n" typ
7934        | RStructList (_, typ) ->
7935            pr "  py_r = put_%s_list (r);\n" typ;
7936            pr "  guestfs_free_%s_list (r);\n" typ
7937        | RHashtable n ->
7938            pr "  py_r = put_table (r);\n";
7939            pr "  free_strings (r);\n"
7940        | RBufferOut _ ->
7941            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
7942            pr "  free (r);\n"
7943       );
7944
7945       pr "  return py_r;\n";
7946       pr "}\n";
7947       pr "\n"
7948   ) all_functions;
7949
7950   (* Table of functions. *)
7951   pr "static PyMethodDef methods[] = {\n";
7952   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
7953   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
7954   List.iter (
7955     fun (name, _, _, _, _, _, _) ->
7956       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
7957         name name
7958   ) all_functions;
7959   pr "  { NULL, NULL, 0, NULL }\n";
7960   pr "};\n";
7961   pr "\n";
7962
7963   (* Init function. *)
7964   pr "\
7965 void
7966 initlibguestfsmod (void)
7967 {
7968   static int initialized = 0;
7969
7970   if (initialized) return;
7971   Py_InitModule ((char *) \"libguestfsmod\", methods);
7972   initialized = 1;
7973 }
7974 "
7975
7976 (* Generate Python module. *)
7977 and generate_python_py () =
7978   generate_header HashStyle LGPLv2;
7979
7980   pr "\
7981 u\"\"\"Python bindings for libguestfs
7982
7983 import guestfs
7984 g = guestfs.GuestFS ()
7985 g.add_drive (\"guest.img\")
7986 g.launch ()
7987 parts = g.list_partitions ()
7988
7989 The guestfs module provides a Python binding to the libguestfs API
7990 for examining and modifying virtual machine disk images.
7991
7992 Amongst the things this is good for: making batch configuration
7993 changes to guests, getting disk used/free statistics (see also:
7994 virt-df), migrating between virtualization systems (see also:
7995 virt-p2v), performing partial backups, performing partial guest
7996 clones, cloning guests and changing registry/UUID/hostname info, and
7997 much else besides.
7998
7999 Libguestfs uses Linux kernel and qemu code, and can access any type of
8000 guest filesystem that Linux and qemu can, including but not limited
8001 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8002 schemes, qcow, qcow2, vmdk.
8003
8004 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8005 LVs, what filesystem is in each LV, etc.).  It can also run commands
8006 in the context of the guest.  Also you can access filesystems over FTP.
8007
8008 Errors which happen while using the API are turned into Python
8009 RuntimeError exceptions.
8010
8011 To create a guestfs handle you usually have to perform the following
8012 sequence of calls:
8013
8014 # Create the handle, call add_drive at least once, and possibly
8015 # several times if the guest has multiple block devices:
8016 g = guestfs.GuestFS ()
8017 g.add_drive (\"guest.img\")
8018
8019 # Launch the qemu subprocess and wait for it to become ready:
8020 g.launch ()
8021
8022 # Now you can issue commands, for example:
8023 logvols = g.lvs ()
8024
8025 \"\"\"
8026
8027 import libguestfsmod
8028
8029 class GuestFS:
8030     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8031
8032     def __init__ (self):
8033         \"\"\"Create a new libguestfs handle.\"\"\"
8034         self._o = libguestfsmod.create ()
8035
8036     def __del__ (self):
8037         libguestfsmod.close (self._o)
8038
8039 ";
8040
8041   List.iter (
8042     fun (name, style, _, flags, _, _, longdesc) ->
8043       pr "    def %s " name;
8044       generate_py_call_args ~handle:"self" (snd style);
8045       pr ":\n";
8046
8047       if not (List.mem NotInDocs flags) then (
8048         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8049         let doc =
8050           match fst style with
8051           | RErr | RInt _ | RInt64 _ | RBool _
8052           | RConstOptString _ | RConstString _
8053           | RString _ | RBufferOut _ -> doc
8054           | RStringList _ ->
8055               doc ^ "\n\nThis function returns a list of strings."
8056           | RStruct (_, typ) ->
8057               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8058           | RStructList (_, typ) ->
8059               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8060           | RHashtable _ ->
8061               doc ^ "\n\nThis function returns a dictionary." in
8062         let doc =
8063           if List.mem ProtocolLimitWarning flags then
8064             doc ^ "\n\n" ^ protocol_limit_warning
8065           else doc in
8066         let doc =
8067           if List.mem DangerWillRobinson flags then
8068             doc ^ "\n\n" ^ danger_will_robinson
8069           else doc in
8070         let doc =
8071           match deprecation_notice flags with
8072           | None -> doc
8073           | Some txt -> doc ^ "\n\n" ^ txt in
8074         let doc = pod2text ~width:60 name doc in
8075         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
8076         let doc = String.concat "\n        " doc in
8077         pr "        u\"\"\"%s\"\"\"\n" doc;
8078       );
8079       pr "        return libguestfsmod.%s " name;
8080       generate_py_call_args ~handle:"self._o" (snd style);
8081       pr "\n";
8082       pr "\n";
8083   ) all_functions
8084
8085 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
8086 and generate_py_call_args ~handle args =
8087   pr "(%s" handle;
8088   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8089   pr ")"
8090
8091 (* Useful if you need the longdesc POD text as plain text.  Returns a
8092  * list of lines.
8093  *
8094  * Because this is very slow (the slowest part of autogeneration),
8095  * we memoize the results.
8096  *)
8097 and pod2text ~width name longdesc =
8098   let key = width, name, longdesc in
8099   try Hashtbl.find pod2text_memo key
8100   with Not_found ->
8101     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
8102     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
8103     close_out chan;
8104     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
8105     let chan = Unix.open_process_in cmd in
8106     let lines = ref [] in
8107     let rec loop i =
8108       let line = input_line chan in
8109       if i = 1 then             (* discard the first line of output *)
8110         loop (i+1)
8111       else (
8112         let line = triml line in
8113         lines := line :: !lines;
8114         loop (i+1)
8115       ) in
8116     let lines = try loop 1 with End_of_file -> List.rev !lines in
8117     Unix.unlink filename;
8118     (match Unix.close_process_in chan with
8119      | Unix.WEXITED 0 -> ()
8120      | Unix.WEXITED i ->
8121          failwithf "pod2text: process exited with non-zero status (%d)" i
8122      | Unix.WSIGNALED i | Unix.WSTOPPED i ->
8123          failwithf "pod2text: process signalled or stopped by signal %d" i
8124     );
8125     Hashtbl.add pod2text_memo key lines;
8126     pod2text_memo_updated ();
8127     lines
8128
8129 (* Generate ruby bindings. *)
8130 and generate_ruby_c () =
8131   generate_header CStyle LGPLv2;
8132
8133   pr "\
8134 #include <stdio.h>
8135 #include <stdlib.h>
8136
8137 #include <ruby.h>
8138
8139 #include \"guestfs.h\"
8140
8141 #include \"extconf.h\"
8142
8143 /* For Ruby < 1.9 */
8144 #ifndef RARRAY_LEN
8145 #define RARRAY_LEN(r) (RARRAY((r))->len)
8146 #endif
8147
8148 static VALUE m_guestfs;                 /* guestfs module */
8149 static VALUE c_guestfs;                 /* guestfs_h handle */
8150 static VALUE e_Error;                   /* used for all errors */
8151
8152 static void ruby_guestfs_free (void *p)
8153 {
8154   if (!p) return;
8155   guestfs_close ((guestfs_h *) p);
8156 }
8157
8158 static VALUE ruby_guestfs_create (VALUE m)
8159 {
8160   guestfs_h *g;
8161
8162   g = guestfs_create ();
8163   if (!g)
8164     rb_raise (e_Error, \"failed to create guestfs handle\");
8165
8166   /* Don't print error messages to stderr by default. */
8167   guestfs_set_error_handler (g, NULL, NULL);
8168
8169   /* Wrap it, and make sure the close function is called when the
8170    * handle goes away.
8171    */
8172   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
8173 }
8174
8175 static VALUE ruby_guestfs_close (VALUE gv)
8176 {
8177   guestfs_h *g;
8178   Data_Get_Struct (gv, guestfs_h, g);
8179
8180   ruby_guestfs_free (g);
8181   DATA_PTR (gv) = NULL;
8182
8183   return Qnil;
8184 }
8185
8186 ";
8187
8188   List.iter (
8189     fun (name, style, _, _, _, _, _) ->
8190       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
8191       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
8192       pr ")\n";
8193       pr "{\n";
8194       pr "  guestfs_h *g;\n";
8195       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
8196       pr "  if (!g)\n";
8197       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
8198         name;
8199       pr "\n";
8200
8201       List.iter (
8202         function
8203         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8204             pr "  Check_Type (%sv, T_STRING);\n" n;
8205             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
8206             pr "  if (!%s)\n" n;
8207             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
8208             pr "              \"%s\", \"%s\");\n" n name
8209         | OptString n ->
8210             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
8211         | StringList n | DeviceList n ->
8212             pr "  char **%s;\n" n;
8213             pr "  Check_Type (%sv, T_ARRAY);\n" n;
8214             pr "  {\n";
8215             pr "    int i, len;\n";
8216             pr "    len = RARRAY_LEN (%sv);\n" n;
8217             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
8218               n;
8219             pr "    for (i = 0; i < len; ++i) {\n";
8220             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
8221             pr "      %s[i] = StringValueCStr (v);\n" n;
8222             pr "    }\n";
8223             pr "    %s[len] = NULL;\n" n;
8224             pr "  }\n";
8225         | Bool n ->
8226             pr "  int %s = RTEST (%sv);\n" n n
8227         | Int n ->
8228             pr "  int %s = NUM2INT (%sv);\n" n n
8229       ) (snd style);
8230       pr "\n";
8231
8232       let error_code =
8233         match fst style with
8234         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8235         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8236         | RConstString _ | RConstOptString _ ->
8237             pr "  const char *r;\n"; "NULL"
8238         | RString _ -> pr "  char *r;\n"; "NULL"
8239         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8240         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8241         | RStructList (_, typ) ->
8242             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8243         | RBufferOut _ ->
8244             pr "  char *r;\n";
8245             pr "  size_t size;\n";
8246             "NULL" in
8247       pr "\n";
8248
8249       pr "  r = guestfs_%s " name;
8250       generate_c_call_args ~handle:"g" style;
8251       pr ";\n";
8252
8253       List.iter (
8254         function
8255         | Pathname _ | Device _ | Dev_or_Path _ | String _
8256         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ -> ()
8257         | StringList n | DeviceList n ->
8258             pr "  free (%s);\n" n
8259       ) (snd style);
8260
8261       pr "  if (r == %s)\n" error_code;
8262       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
8263       pr "\n";
8264
8265       (match fst style with
8266        | RErr ->
8267            pr "  return Qnil;\n"
8268        | RInt _ | RBool _ ->
8269            pr "  return INT2NUM (r);\n"
8270        | RInt64 _ ->
8271            pr "  return ULL2NUM (r);\n"
8272        | RConstString _ ->
8273            pr "  return rb_str_new2 (r);\n";
8274        | RConstOptString _ ->
8275            pr "  if (r)\n";
8276            pr "    return rb_str_new2 (r);\n";
8277            pr "  else\n";
8278            pr "    return Qnil;\n";
8279        | RString _ ->
8280            pr "  VALUE rv = rb_str_new2 (r);\n";
8281            pr "  free (r);\n";
8282            pr "  return rv;\n";
8283        | RStringList _ ->
8284            pr "  int i, len = 0;\n";
8285            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
8286            pr "  VALUE rv = rb_ary_new2 (len);\n";
8287            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
8288            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
8289            pr "    free (r[i]);\n";
8290            pr "  }\n";
8291            pr "  free (r);\n";
8292            pr "  return rv;\n"
8293        | RStruct (_, typ) ->
8294            let cols = cols_of_struct typ in
8295            generate_ruby_struct_code typ cols
8296        | RStructList (_, typ) ->
8297            let cols = cols_of_struct typ in
8298            generate_ruby_struct_list_code typ cols
8299        | RHashtable _ ->
8300            pr "  VALUE rv = rb_hash_new ();\n";
8301            pr "  int i;\n";
8302            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
8303            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
8304            pr "    free (r[i]);\n";
8305            pr "    free (r[i+1]);\n";
8306            pr "  }\n";
8307            pr "  free (r);\n";
8308            pr "  return rv;\n"
8309        | RBufferOut _ ->
8310            pr "  VALUE rv = rb_str_new (r, size);\n";
8311            pr "  free (r);\n";
8312            pr "  return rv;\n";
8313       );
8314
8315       pr "}\n";
8316       pr "\n"
8317   ) all_functions;
8318
8319   pr "\
8320 /* Initialize the module. */
8321 void Init__guestfs ()
8322 {
8323   m_guestfs = rb_define_module (\"Guestfs\");
8324   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
8325   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
8326
8327   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
8328   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
8329
8330 ";
8331   (* Define the rest of the methods. *)
8332   List.iter (
8333     fun (name, style, _, _, _, _, _) ->
8334       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
8335       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
8336   ) all_functions;
8337
8338   pr "}\n"
8339
8340 (* Ruby code to return a struct. *)
8341 and generate_ruby_struct_code typ cols =
8342   pr "  VALUE rv = rb_hash_new ();\n";
8343   List.iter (
8344     function
8345     | name, FString ->
8346         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
8347     | name, FBuffer ->
8348         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
8349     | name, FUUID ->
8350         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
8351     | name, (FBytes|FUInt64) ->
8352         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8353     | name, FInt64 ->
8354         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
8355     | name, FUInt32 ->
8356         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
8357     | name, FInt32 ->
8358         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
8359     | name, FOptPercent ->
8360         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
8361     | name, FChar -> (* XXX wrong? *)
8362         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
8363   ) cols;
8364   pr "  guestfs_free_%s (r);\n" typ;
8365   pr "  return rv;\n"
8366
8367 (* Ruby code to return a struct list. *)
8368 and generate_ruby_struct_list_code typ cols =
8369   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
8370   pr "  int i;\n";
8371   pr "  for (i = 0; i < r->len; ++i) {\n";
8372   pr "    VALUE hv = rb_hash_new ();\n";
8373   List.iter (
8374     function
8375     | name, FString ->
8376         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
8377     | name, FBuffer ->
8378         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
8379     | name, FUUID ->
8380         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
8381     | name, (FBytes|FUInt64) ->
8382         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8383     | name, FInt64 ->
8384         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
8385     | name, FUInt32 ->
8386         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
8387     | name, FInt32 ->
8388         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
8389     | name, FOptPercent ->
8390         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
8391     | name, FChar -> (* XXX wrong? *)
8392         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
8393   ) cols;
8394   pr "    rb_ary_push (rv, hv);\n";
8395   pr "  }\n";
8396   pr "  guestfs_free_%s_list (r);\n" typ;
8397   pr "  return rv;\n"
8398
8399 (* Generate Java bindings GuestFS.java file. *)
8400 and generate_java_java () =
8401   generate_header CStyle LGPLv2;
8402
8403   pr "\
8404 package com.redhat.et.libguestfs;
8405
8406 import java.util.HashMap;
8407 import com.redhat.et.libguestfs.LibGuestFSException;
8408 import com.redhat.et.libguestfs.PV;
8409 import com.redhat.et.libguestfs.VG;
8410 import com.redhat.et.libguestfs.LV;
8411 import com.redhat.et.libguestfs.Stat;
8412 import com.redhat.et.libguestfs.StatVFS;
8413 import com.redhat.et.libguestfs.IntBool;
8414 import com.redhat.et.libguestfs.Dirent;
8415
8416 /**
8417  * The GuestFS object is a libguestfs handle.
8418  *
8419  * @author rjones
8420  */
8421 public class GuestFS {
8422   // Load the native code.
8423   static {
8424     System.loadLibrary (\"guestfs_jni\");
8425   }
8426
8427   /**
8428    * The native guestfs_h pointer.
8429    */
8430   long g;
8431
8432   /**
8433    * Create a libguestfs handle.
8434    *
8435    * @throws LibGuestFSException
8436    */
8437   public GuestFS () throws LibGuestFSException
8438   {
8439     g = _create ();
8440   }
8441   private native long _create () throws LibGuestFSException;
8442
8443   /**
8444    * Close a libguestfs handle.
8445    *
8446    * You can also leave handles to be collected by the garbage
8447    * collector, but this method ensures that the resources used
8448    * by the handle are freed up immediately.  If you call any
8449    * other methods after closing the handle, you will get an
8450    * exception.
8451    *
8452    * @throws LibGuestFSException
8453    */
8454   public void close () throws LibGuestFSException
8455   {
8456     if (g != 0)
8457       _close (g);
8458     g = 0;
8459   }
8460   private native void _close (long g) throws LibGuestFSException;
8461
8462   public void finalize () throws LibGuestFSException
8463   {
8464     close ();
8465   }
8466
8467 ";
8468
8469   List.iter (
8470     fun (name, style, _, flags, _, shortdesc, longdesc) ->
8471       if not (List.mem NotInDocs flags); then (
8472         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8473         let doc =
8474           if List.mem ProtocolLimitWarning flags then
8475             doc ^ "\n\n" ^ protocol_limit_warning
8476           else doc in
8477         let doc =
8478           if List.mem DangerWillRobinson flags then
8479             doc ^ "\n\n" ^ danger_will_robinson
8480           else doc in
8481         let doc =
8482           match deprecation_notice flags with
8483           | None -> doc
8484           | Some txt -> doc ^ "\n\n" ^ txt in
8485         let doc = pod2text ~width:60 name doc in
8486         let doc = List.map (            (* RHBZ#501883 *)
8487           function
8488           | "" -> "<p>"
8489           | nonempty -> nonempty
8490         ) doc in
8491         let doc = String.concat "\n   * " doc in
8492
8493         pr "  /**\n";
8494         pr "   * %s\n" shortdesc;
8495         pr "   * <p>\n";
8496         pr "   * %s\n" doc;
8497         pr "   * @throws LibGuestFSException\n";
8498         pr "   */\n";
8499         pr "  ";
8500       );
8501       generate_java_prototype ~public:true ~semicolon:false name style;
8502       pr "\n";
8503       pr "  {\n";
8504       pr "    if (g == 0)\n";
8505       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
8506         name;
8507       pr "    ";
8508       if fst style <> RErr then pr "return ";
8509       pr "_%s " name;
8510       generate_java_call_args ~handle:"g" (snd style);
8511       pr ";\n";
8512       pr "  }\n";
8513       pr "  ";
8514       generate_java_prototype ~privat:true ~native:true name style;
8515       pr "\n";
8516       pr "\n";
8517   ) all_functions;
8518
8519   pr "}\n"
8520
8521 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
8522 and generate_java_call_args ~handle args =
8523   pr "(%s" handle;
8524   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
8525   pr ")"
8526
8527 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
8528     ?(semicolon=true) name style =
8529   if privat then pr "private ";
8530   if public then pr "public ";
8531   if native then pr "native ";
8532
8533   (* return type *)
8534   (match fst style with
8535    | RErr -> pr "void ";
8536    | RInt _ -> pr "int ";
8537    | RInt64 _ -> pr "long ";
8538    | RBool _ -> pr "boolean ";
8539    | RConstString _ | RConstOptString _ | RString _
8540    | RBufferOut _ -> pr "String ";
8541    | RStringList _ -> pr "String[] ";
8542    | RStruct (_, typ) ->
8543        let name = java_name_of_struct typ in
8544        pr "%s " name;
8545    | RStructList (_, typ) ->
8546        let name = java_name_of_struct typ in
8547        pr "%s[] " name;
8548    | RHashtable _ -> pr "HashMap<String,String> ";
8549   );
8550
8551   if native then pr "_%s " name else pr "%s " name;
8552   pr "(";
8553   let needs_comma = ref false in
8554   if native then (
8555     pr "long g";
8556     needs_comma := true
8557   );
8558
8559   (* args *)
8560   List.iter (
8561     fun arg ->
8562       if !needs_comma then pr ", ";
8563       needs_comma := true;
8564
8565       match arg with
8566       | Pathname n
8567       | Device n | Dev_or_Path n
8568       | String n
8569       | OptString n
8570       | FileIn n
8571       | FileOut n ->
8572           pr "String %s" n
8573       | StringList n | DeviceList n ->
8574           pr "String[] %s" n
8575       | Bool n ->
8576           pr "boolean %s" n
8577       | Int n ->
8578           pr "int %s" n
8579   ) (snd style);
8580
8581   pr ")\n";
8582   pr "    throws LibGuestFSException";
8583   if semicolon then pr ";"
8584
8585 and generate_java_struct jtyp cols =
8586   generate_header CStyle LGPLv2;
8587
8588   pr "\
8589 package com.redhat.et.libguestfs;
8590
8591 /**
8592  * Libguestfs %s structure.
8593  *
8594  * @author rjones
8595  * @see GuestFS
8596  */
8597 public class %s {
8598 " jtyp jtyp;
8599
8600   List.iter (
8601     function
8602     | name, FString
8603     | name, FUUID
8604     | name, FBuffer -> pr "  public String %s;\n" name
8605     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
8606     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
8607     | name, FChar -> pr "  public char %s;\n" name
8608     | name, FOptPercent ->
8609         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
8610         pr "  public float %s;\n" name
8611   ) cols;
8612
8613   pr "}\n"
8614
8615 and generate_java_c () =
8616   generate_header CStyle LGPLv2;
8617
8618   pr "\
8619 #include <stdio.h>
8620 #include <stdlib.h>
8621 #include <string.h>
8622
8623 #include \"com_redhat_et_libguestfs_GuestFS.h\"
8624 #include \"guestfs.h\"
8625
8626 /* Note that this function returns.  The exception is not thrown
8627  * until after the wrapper function returns.
8628  */
8629 static void
8630 throw_exception (JNIEnv *env, const char *msg)
8631 {
8632   jclass cl;
8633   cl = (*env)->FindClass (env,
8634                           \"com/redhat/et/libguestfs/LibGuestFSException\");
8635   (*env)->ThrowNew (env, cl, msg);
8636 }
8637
8638 JNIEXPORT jlong JNICALL
8639 Java_com_redhat_et_libguestfs_GuestFS__1create
8640   (JNIEnv *env, jobject obj)
8641 {
8642   guestfs_h *g;
8643
8644   g = guestfs_create ();
8645   if (g == NULL) {
8646     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
8647     return 0;
8648   }
8649   guestfs_set_error_handler (g, NULL, NULL);
8650   return (jlong) (long) g;
8651 }
8652
8653 JNIEXPORT void JNICALL
8654 Java_com_redhat_et_libguestfs_GuestFS__1close
8655   (JNIEnv *env, jobject obj, jlong jg)
8656 {
8657   guestfs_h *g = (guestfs_h *) (long) jg;
8658   guestfs_close (g);
8659 }
8660
8661 ";
8662
8663   List.iter (
8664     fun (name, style, _, _, _, _, _) ->
8665       pr "JNIEXPORT ";
8666       (match fst style with
8667        | RErr -> pr "void ";
8668        | RInt _ -> pr "jint ";
8669        | RInt64 _ -> pr "jlong ";
8670        | RBool _ -> pr "jboolean ";
8671        | RConstString _ | RConstOptString _ | RString _
8672        | RBufferOut _ -> pr "jstring ";
8673        | RStruct _ | RHashtable _ ->
8674            pr "jobject ";
8675        | RStringList _ | RStructList _ ->
8676            pr "jobjectArray ";
8677       );
8678       pr "JNICALL\n";
8679       pr "Java_com_redhat_et_libguestfs_GuestFS_";
8680       pr "%s" (replace_str ("_" ^ name) "_" "_1");
8681       pr "\n";
8682       pr "  (JNIEnv *env, jobject obj, jlong jg";
8683       List.iter (
8684         function
8685         | Pathname n
8686         | Device n | Dev_or_Path n
8687         | String n
8688         | OptString n
8689         | FileIn n
8690         | FileOut n ->
8691             pr ", jstring j%s" n
8692         | StringList n | DeviceList n ->
8693             pr ", jobjectArray j%s" n
8694         | Bool n ->
8695             pr ", jboolean j%s" n
8696         | Int n ->
8697             pr ", jint j%s" n
8698       ) (snd style);
8699       pr ")\n";
8700       pr "{\n";
8701       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
8702       let error_code, no_ret =
8703         match fst style with
8704         | RErr -> pr "  int r;\n"; "-1", ""
8705         | RBool _
8706         | RInt _ -> pr "  int r;\n"; "-1", "0"
8707         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
8708         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8709         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
8710         | RString _ ->
8711             pr "  jstring jr;\n";
8712             pr "  char *r;\n"; "NULL", "NULL"
8713         | RStringList _ ->
8714             pr "  jobjectArray jr;\n";
8715             pr "  int r_len;\n";
8716             pr "  jclass cl;\n";
8717             pr "  jstring jstr;\n";
8718             pr "  char **r;\n"; "NULL", "NULL"
8719         | RStruct (_, typ) ->
8720             pr "  jobject jr;\n";
8721             pr "  jclass cl;\n";
8722             pr "  jfieldID fl;\n";
8723             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
8724         | RStructList (_, typ) ->
8725             pr "  jobjectArray jr;\n";
8726             pr "  jclass cl;\n";
8727             pr "  jfieldID fl;\n";
8728             pr "  jobject jfl;\n";
8729             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
8730         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
8731         | RBufferOut _ ->
8732             pr "  jstring jr;\n";
8733             pr "  char *r;\n";
8734             pr "  size_t size;\n";
8735             "NULL", "NULL" in
8736       List.iter (
8737         function
8738         | Pathname n
8739         | Device n | Dev_or_Path n
8740         | String n
8741         | OptString n
8742         | FileIn n
8743         | FileOut n ->
8744             pr "  const char *%s;\n" n
8745         | StringList n | DeviceList n ->
8746             pr "  int %s_len;\n" n;
8747             pr "  const char **%s;\n" n
8748         | Bool n
8749         | Int n ->
8750             pr "  int %s;\n" n
8751       ) (snd style);
8752
8753       let needs_i =
8754         (match fst style with
8755          | RStringList _ | RStructList _ -> true
8756          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
8757          | RConstOptString _
8758          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
8759           List.exists (function
8760                        | StringList _ -> true
8761                        | DeviceList _ -> true
8762                        | _ -> false) (snd style) in
8763       if needs_i then
8764         pr "  int i;\n";
8765
8766       pr "\n";
8767
8768       (* Get the parameters. *)
8769       List.iter (
8770         function
8771         | Pathname n
8772         | Device n | Dev_or_Path n
8773         | String n
8774         | FileIn n
8775         | FileOut n ->
8776             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
8777         | OptString n ->
8778             (* This is completely undocumented, but Java null becomes
8779              * a NULL parameter.
8780              *)
8781             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
8782         | StringList n | DeviceList n ->
8783             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
8784             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
8785             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8786             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8787               n;
8788             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
8789             pr "  }\n";
8790             pr "  %s[%s_len] = NULL;\n" n n;
8791         | Bool n
8792         | Int n ->
8793             pr "  %s = j%s;\n" n n
8794       ) (snd style);
8795
8796       (* Make the call. *)
8797       pr "  r = guestfs_%s " name;
8798       generate_c_call_args ~handle:"g" style;
8799       pr ";\n";
8800
8801       (* Release the parameters. *)
8802       List.iter (
8803         function
8804         | Pathname n
8805         | Device n | Dev_or_Path n
8806         | String n
8807         | FileIn n
8808         | FileOut n ->
8809             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8810         | OptString n ->
8811             pr "  if (j%s)\n" n;
8812             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
8813         | StringList n | DeviceList n ->
8814             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
8815             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
8816               n;
8817             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
8818             pr "  }\n";
8819             pr "  free (%s);\n" n
8820         | Bool n
8821         | Int n -> ()
8822       ) (snd style);
8823
8824       (* Check for errors. *)
8825       pr "  if (r == %s) {\n" error_code;
8826       pr "    throw_exception (env, guestfs_last_error (g));\n";
8827       pr "    return %s;\n" no_ret;
8828       pr "  }\n";
8829
8830       (* Return value. *)
8831       (match fst style with
8832        | RErr -> ()
8833        | RInt _ -> pr "  return (jint) r;\n"
8834        | RBool _ -> pr "  return (jboolean) r;\n"
8835        | RInt64 _ -> pr "  return (jlong) r;\n"
8836        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
8837        | RConstOptString _ ->
8838            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
8839        | RString _ ->
8840            pr "  jr = (*env)->NewStringUTF (env, r);\n";
8841            pr "  free (r);\n";
8842            pr "  return jr;\n"
8843        | RStringList _ ->
8844            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
8845            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
8846            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
8847            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
8848            pr "  for (i = 0; i < r_len; ++i) {\n";
8849            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
8850            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
8851            pr "    free (r[i]);\n";
8852            pr "  }\n";
8853            pr "  free (r);\n";
8854            pr "  return jr;\n"
8855        | RStruct (_, typ) ->
8856            let jtyp = java_name_of_struct typ in
8857            let cols = cols_of_struct typ in
8858            generate_java_struct_return typ jtyp cols
8859        | RStructList (_, typ) ->
8860            let jtyp = java_name_of_struct typ in
8861            let cols = cols_of_struct typ in
8862            generate_java_struct_list_return typ jtyp cols
8863        | RHashtable _ ->
8864            (* XXX *)
8865            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
8866            pr "  return NULL;\n"
8867        | RBufferOut _ ->
8868            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
8869            pr "  free (r);\n";
8870            pr "  return jr;\n"
8871       );
8872
8873       pr "}\n";
8874       pr "\n"
8875   ) all_functions
8876
8877 and generate_java_struct_return typ jtyp cols =
8878   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8879   pr "  jr = (*env)->AllocObject (env, cl);\n";
8880   List.iter (
8881     function
8882     | name, FString ->
8883         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8884         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
8885     | name, FUUID ->
8886         pr "  {\n";
8887         pr "    char s[33];\n";
8888         pr "    memcpy (s, r->%s, 32);\n" name;
8889         pr "    s[32] = 0;\n";
8890         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8891         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8892         pr "  }\n";
8893     | name, FBuffer ->
8894         pr "  {\n";
8895         pr "    int len = r->%s_len;\n" name;
8896         pr "    char s[len+1];\n";
8897         pr "    memcpy (s, r->%s, len);\n" name;
8898         pr "    s[len] = 0;\n";
8899         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8900         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
8901         pr "  }\n";
8902     | name, (FBytes|FUInt64|FInt64) ->
8903         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8904         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8905     | name, (FUInt32|FInt32) ->
8906         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8907         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8908     | name, FOptPercent ->
8909         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8910         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
8911     | name, FChar ->
8912         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8913         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
8914   ) cols;
8915   pr "  free (r);\n";
8916   pr "  return jr;\n"
8917
8918 and generate_java_struct_list_return typ jtyp cols =
8919   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
8920   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
8921   pr "  for (i = 0; i < r->len; ++i) {\n";
8922   pr "    jfl = (*env)->AllocObject (env, cl);\n";
8923   List.iter (
8924     function
8925     | name, FString ->
8926         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8927         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
8928     | name, FUUID ->
8929         pr "    {\n";
8930         pr "      char s[33];\n";
8931         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
8932         pr "      s[32] = 0;\n";
8933         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8934         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8935         pr "    }\n";
8936     | name, FBuffer ->
8937         pr "    {\n";
8938         pr "      int len = r->val[i].%s_len;\n" name;
8939         pr "      char s[len+1];\n";
8940         pr "      memcpy (s, r->val[i].%s, len);\n" name;
8941         pr "      s[len] = 0;\n";
8942         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
8943         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
8944         pr "    }\n";
8945     | name, (FBytes|FUInt64|FInt64) ->
8946         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
8947         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8948     | name, (FUInt32|FInt32) ->
8949         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
8950         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8951     | name, FOptPercent ->
8952         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
8953         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
8954     | name, FChar ->
8955         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
8956         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
8957   ) cols;
8958   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
8959   pr "  }\n";
8960   pr "  guestfs_free_%s_list (r);\n" typ;
8961   pr "  return jr;\n"
8962
8963 and generate_java_makefile_inc () =
8964   generate_header HashStyle GPLv2;
8965
8966   pr "java_built_sources = \\\n";
8967   List.iter (
8968     fun (typ, jtyp) ->
8969         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
8970   ) java_structs;
8971   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
8972
8973 and generate_haskell_hs () =
8974   generate_header HaskellStyle LGPLv2;
8975
8976   (* XXX We only know how to generate partial FFI for Haskell
8977    * at the moment.  Please help out!
8978    *)
8979   let can_generate style =
8980     match style with
8981     | RErr, _
8982     | RInt _, _
8983     | RInt64 _, _ -> true
8984     | RBool _, _
8985     | RConstString _, _
8986     | RConstOptString _, _
8987     | RString _, _
8988     | RStringList _, _
8989     | RStruct _, _
8990     | RStructList _, _
8991     | RHashtable _, _
8992     | RBufferOut _, _ -> false in
8993
8994   pr "\
8995 {-# INCLUDE <guestfs.h> #-}
8996 {-# LANGUAGE ForeignFunctionInterface #-}
8997
8998 module Guestfs (
8999   create";
9000
9001   (* List out the names of the actions we want to export. *)
9002   List.iter (
9003     fun (name, style, _, _, _, _, _) ->
9004       if can_generate style then pr ",\n  %s" name
9005   ) all_functions;
9006
9007   pr "
9008   ) where
9009 import Foreign
9010 import Foreign.C
9011 import Foreign.C.Types
9012 import IO
9013 import Control.Exception
9014 import Data.Typeable
9015
9016 data GuestfsS = GuestfsS            -- represents the opaque C struct
9017 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9018 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9019
9020 -- XXX define properly later XXX
9021 data PV = PV
9022 data VG = VG
9023 data LV = LV
9024 data IntBool = IntBool
9025 data Stat = Stat
9026 data StatVFS = StatVFS
9027 data Hashtable = Hashtable
9028
9029 foreign import ccall unsafe \"guestfs_create\" c_create
9030   :: IO GuestfsP
9031 foreign import ccall unsafe \"&guestfs_close\" c_close
9032   :: FunPtr (GuestfsP -> IO ())
9033 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9034   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9035
9036 create :: IO GuestfsH
9037 create = do
9038   p <- c_create
9039   c_set_error_handler p nullPtr nullPtr
9040   h <- newForeignPtr c_close p
9041   return h
9042
9043 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9044   :: GuestfsP -> IO CString
9045
9046 -- last_error :: GuestfsH -> IO (Maybe String)
9047 -- last_error h = do
9048 --   str <- withForeignPtr h (\\p -> c_last_error p)
9049 --   maybePeek peekCString str
9050
9051 last_error :: GuestfsH -> IO (String)
9052 last_error h = do
9053   str <- withForeignPtr h (\\p -> c_last_error p)
9054   if (str == nullPtr)
9055     then return \"no error\"
9056     else peekCString str
9057
9058 ";
9059
9060   (* Generate wrappers for each foreign function. *)
9061   List.iter (
9062     fun (name, style, _, _, _, _, _) ->
9063       if can_generate style then (
9064         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
9065         pr "  :: ";
9066         generate_haskell_prototype ~handle:"GuestfsP" style;
9067         pr "\n";
9068         pr "\n";
9069         pr "%s :: " name;
9070         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
9071         pr "\n";
9072         pr "%s %s = do\n" name
9073           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
9074         pr "  r <- ";
9075         (* Convert pointer arguments using with* functions. *)
9076         List.iter (
9077           function
9078           | FileIn n
9079           | FileOut n
9080           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
9081           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
9082           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
9083           | Bool _ | Int _ -> ()
9084         ) (snd style);
9085         (* Convert integer arguments. *)
9086         let args =
9087           List.map (
9088             function
9089             | Bool n -> sprintf "(fromBool %s)" n
9090             | Int n -> sprintf "(fromIntegral %s)" n
9091             | FileIn n | FileOut n
9092             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
9093           ) (snd style) in
9094         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
9095           (String.concat " " ("p" :: args));
9096         (match fst style with
9097          | RErr | RInt _ | RInt64 _ | RBool _ ->
9098              pr "  if (r == -1)\n";
9099              pr "    then do\n";
9100              pr "      err <- last_error h\n";
9101              pr "      fail err\n";
9102          | RConstString _ | RConstOptString _ | RString _
9103          | RStringList _ | RStruct _
9104          | RStructList _ | RHashtable _ | RBufferOut _ ->
9105              pr "  if (r == nullPtr)\n";
9106              pr "    then do\n";
9107              pr "      err <- last_error h\n";
9108              pr "      fail err\n";
9109         );
9110         (match fst style with
9111          | RErr ->
9112              pr "    else return ()\n"
9113          | RInt _ ->
9114              pr "    else return (fromIntegral r)\n"
9115          | RInt64 _ ->
9116              pr "    else return (fromIntegral r)\n"
9117          | RBool _ ->
9118              pr "    else return (toBool r)\n"
9119          | RConstString _
9120          | RConstOptString _
9121          | RString _
9122          | RStringList _
9123          | RStruct _
9124          | RStructList _
9125          | RHashtable _
9126          | RBufferOut _ ->
9127              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
9128         );
9129         pr "\n";
9130       )
9131   ) all_functions
9132
9133 and generate_haskell_prototype ~handle ?(hs = false) style =
9134   pr "%s -> " handle;
9135   let string = if hs then "String" else "CString" in
9136   let int = if hs then "Int" else "CInt" in
9137   let bool = if hs then "Bool" else "CInt" in
9138   let int64 = if hs then "Integer" else "Int64" in
9139   List.iter (
9140     fun arg ->
9141       (match arg with
9142        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
9143        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
9144        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
9145        | Bool _ -> pr "%s" bool
9146        | Int _ -> pr "%s" int
9147        | FileIn _ -> pr "%s" string
9148        | FileOut _ -> pr "%s" string
9149       );
9150       pr " -> ";
9151   ) (snd style);
9152   pr "IO (";
9153   (match fst style with
9154    | RErr -> if not hs then pr "CInt"
9155    | RInt _ -> pr "%s" int
9156    | RInt64 _ -> pr "%s" int64
9157    | RBool _ -> pr "%s" bool
9158    | RConstString _ -> pr "%s" string
9159    | RConstOptString _ -> pr "Maybe %s" string
9160    | RString _ -> pr "%s" string
9161    | RStringList _ -> pr "[%s]" string
9162    | RStruct (_, typ) ->
9163        let name = java_name_of_struct typ in
9164        pr "%s" name
9165    | RStructList (_, typ) ->
9166        let name = java_name_of_struct typ in
9167        pr "[%s]" name
9168    | RHashtable _ -> pr "Hashtable"
9169    | RBufferOut _ -> pr "%s" string
9170   );
9171   pr ")"
9172
9173 and generate_bindtests () =
9174   generate_header CStyle LGPLv2;
9175
9176   pr "\
9177 #include <stdio.h>
9178 #include <stdlib.h>
9179 #include <inttypes.h>
9180 #include <string.h>
9181
9182 #include \"guestfs.h\"
9183 #include \"guestfs-internal-actions.h\"
9184 #include \"guestfs_protocol.h\"
9185
9186 #define error guestfs_error
9187 #define safe_calloc guestfs_safe_calloc
9188 #define safe_malloc guestfs_safe_malloc
9189
9190 static void
9191 print_strings (char *const *argv)
9192 {
9193   int argc;
9194
9195   printf (\"[\");
9196   for (argc = 0; argv[argc] != NULL; ++argc) {
9197     if (argc > 0) printf (\", \");
9198     printf (\"\\\"%%s\\\"\", argv[argc]);
9199   }
9200   printf (\"]\\n\");
9201 }
9202
9203 /* The test0 function prints its parameters to stdout. */
9204 ";
9205
9206   let test0, tests =
9207     match test_functions with
9208     | [] -> assert false
9209     | test0 :: tests -> test0, tests in
9210
9211   let () =
9212     let (name, style, _, _, _, _, _) = test0 in
9213     generate_prototype ~extern:false ~semicolon:false ~newline:true
9214       ~handle:"g" ~prefix:"guestfs__" name style;
9215     pr "{\n";
9216     List.iter (
9217       function
9218       | Pathname n
9219       | Device n | Dev_or_Path n
9220       | String n
9221       | FileIn n
9222       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
9223       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
9224       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
9225       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
9226       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
9227     ) (snd style);
9228     pr "  /* Java changes stdout line buffering so we need this: */\n";
9229     pr "  fflush (stdout);\n";
9230     pr "  return 0;\n";
9231     pr "}\n";
9232     pr "\n" in
9233
9234   List.iter (
9235     fun (name, style, _, _, _, _, _) ->
9236       if String.sub name (String.length name - 3) 3 <> "err" then (
9237         pr "/* Test normal return. */\n";
9238         generate_prototype ~extern:false ~semicolon:false ~newline:true
9239           ~handle:"g" ~prefix:"guestfs__" name style;
9240         pr "{\n";
9241         (match fst style with
9242          | RErr ->
9243              pr "  return 0;\n"
9244          | RInt _ ->
9245              pr "  int r;\n";
9246              pr "  sscanf (val, \"%%d\", &r);\n";
9247              pr "  return r;\n"
9248          | RInt64 _ ->
9249              pr "  int64_t r;\n";
9250              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
9251              pr "  return r;\n"
9252          | RBool _ ->
9253              pr "  return strcmp (val, \"true\") == 0;\n"
9254          | RConstString _
9255          | RConstOptString _ ->
9256              (* Can't return the input string here.  Return a static
9257               * string so we ensure we get a segfault if the caller
9258               * tries to free it.
9259               *)
9260              pr "  return \"static string\";\n"
9261          | RString _ ->
9262              pr "  return strdup (val);\n"
9263          | RStringList _ ->
9264              pr "  char **strs;\n";
9265              pr "  int n, i;\n";
9266              pr "  sscanf (val, \"%%d\", &n);\n";
9267              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
9268              pr "  for (i = 0; i < n; ++i) {\n";
9269              pr "    strs[i] = safe_malloc (g, 16);\n";
9270              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
9271              pr "  }\n";
9272              pr "  strs[n] = NULL;\n";
9273              pr "  return strs;\n"
9274          | RStruct (_, typ) ->
9275              pr "  struct guestfs_%s *r;\n" typ;
9276              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9277              pr "  return r;\n"
9278          | RStructList (_, typ) ->
9279              pr "  struct guestfs_%s_list *r;\n" typ;
9280              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
9281              pr "  sscanf (val, \"%%d\", &r->len);\n";
9282              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
9283              pr "  return r;\n"
9284          | RHashtable _ ->
9285              pr "  char **strs;\n";
9286              pr "  int n, i;\n";
9287              pr "  sscanf (val, \"%%d\", &n);\n";
9288              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
9289              pr "  for (i = 0; i < n; ++i) {\n";
9290              pr "    strs[i*2] = safe_malloc (g, 16);\n";
9291              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
9292              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
9293              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
9294              pr "  }\n";
9295              pr "  strs[n*2] = NULL;\n";
9296              pr "  return strs;\n"
9297          | RBufferOut _ ->
9298              pr "  return strdup (val);\n"
9299         );
9300         pr "}\n";
9301         pr "\n"
9302       ) else (
9303         pr "/* Test error return. */\n";
9304         generate_prototype ~extern:false ~semicolon:false ~newline:true
9305           ~handle:"g" ~prefix:"guestfs__" name style;
9306         pr "{\n";
9307         pr "  error (g, \"error\");\n";
9308         (match fst style with
9309          | RErr | RInt _ | RInt64 _ | RBool _ ->
9310              pr "  return -1;\n"
9311          | RConstString _ | RConstOptString _
9312          | RString _ | RStringList _ | RStruct _
9313          | RStructList _
9314          | RHashtable _
9315          | RBufferOut _ ->
9316              pr "  return NULL;\n"
9317         );
9318         pr "}\n";
9319         pr "\n"
9320       )
9321   ) tests
9322
9323 and generate_ocaml_bindtests () =
9324   generate_header OCamlStyle GPLv2;
9325
9326   pr "\
9327 let () =
9328   let g = Guestfs.create () in
9329 ";
9330
9331   let mkargs args =
9332     String.concat " " (
9333       List.map (
9334         function
9335         | CallString s -> "\"" ^ s ^ "\""
9336         | CallOptString None -> "None"
9337         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
9338         | CallStringList xs ->
9339             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
9340         | CallInt i when i >= 0 -> string_of_int i
9341         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
9342         | CallBool b -> string_of_bool b
9343       ) args
9344     )
9345   in
9346
9347   generate_lang_bindtests (
9348     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
9349   );
9350
9351   pr "print_endline \"EOF\"\n"
9352
9353 and generate_perl_bindtests () =
9354   pr "#!/usr/bin/perl -w\n";
9355   generate_header HashStyle GPLv2;
9356
9357   pr "\
9358 use strict;
9359
9360 use Sys::Guestfs;
9361
9362 my $g = Sys::Guestfs->new ();
9363 ";
9364
9365   let mkargs args =
9366     String.concat ", " (
9367       List.map (
9368         function
9369         | CallString s -> "\"" ^ s ^ "\""
9370         | CallOptString None -> "undef"
9371         | CallOptString (Some s) -> sprintf "\"%s\"" s
9372         | CallStringList xs ->
9373             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9374         | CallInt i -> string_of_int i
9375         | CallBool b -> if b then "1" else "0"
9376       ) args
9377     )
9378   in
9379
9380   generate_lang_bindtests (
9381     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
9382   );
9383
9384   pr "print \"EOF\\n\"\n"
9385
9386 and generate_python_bindtests () =
9387   generate_header HashStyle GPLv2;
9388
9389   pr "\
9390 import guestfs
9391
9392 g = guestfs.GuestFS ()
9393 ";
9394
9395   let mkargs args =
9396     String.concat ", " (
9397       List.map (
9398         function
9399         | CallString s -> "\"" ^ s ^ "\""
9400         | CallOptString None -> "None"
9401         | CallOptString (Some s) -> sprintf "\"%s\"" s
9402         | CallStringList xs ->
9403             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9404         | CallInt i -> string_of_int i
9405         | CallBool b -> if b then "1" else "0"
9406       ) args
9407     )
9408   in
9409
9410   generate_lang_bindtests (
9411     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
9412   );
9413
9414   pr "print \"EOF\"\n"
9415
9416 and generate_ruby_bindtests () =
9417   generate_header HashStyle GPLv2;
9418
9419   pr "\
9420 require 'guestfs'
9421
9422 g = Guestfs::create()
9423 ";
9424
9425   let mkargs args =
9426     String.concat ", " (
9427       List.map (
9428         function
9429         | CallString s -> "\"" ^ s ^ "\""
9430         | CallOptString None -> "nil"
9431         | CallOptString (Some s) -> sprintf "\"%s\"" s
9432         | CallStringList xs ->
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 "print \"EOF\\n\"\n"
9445
9446 and generate_java_bindtests () =
9447   generate_header CStyle GPLv2;
9448
9449   pr "\
9450 import com.redhat.et.libguestfs.*;
9451
9452 public class Bindtests {
9453     public static void main (String[] argv)
9454     {
9455         try {
9456             GuestFS g = new GuestFS ();
9457 ";
9458
9459   let mkargs args =
9460     String.concat ", " (
9461       List.map (
9462         function
9463         | CallString s -> "\"" ^ s ^ "\""
9464         | CallOptString None -> "null"
9465         | CallOptString (Some s) -> sprintf "\"%s\"" s
9466         | CallStringList xs ->
9467             "new String[]{" ^
9468               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
9469         | CallInt i -> string_of_int i
9470         | CallBool b -> string_of_bool b
9471       ) args
9472     )
9473   in
9474
9475   generate_lang_bindtests (
9476     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
9477   );
9478
9479   pr "
9480             System.out.println (\"EOF\");
9481         }
9482         catch (Exception exn) {
9483             System.err.println (exn);
9484             System.exit (1);
9485         }
9486     }
9487 }
9488 "
9489
9490 and generate_haskell_bindtests () =
9491   generate_header HaskellStyle GPLv2;
9492
9493   pr "\
9494 module Bindtests where
9495 import qualified Guestfs
9496
9497 main = do
9498   g <- Guestfs.create
9499 ";
9500
9501   let mkargs args =
9502     String.concat " " (
9503       List.map (
9504         function
9505         | CallString s -> "\"" ^ s ^ "\""
9506         | CallOptString None -> "Nothing"
9507         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
9508         | CallStringList xs ->
9509             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
9510         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
9511         | CallInt i -> string_of_int i
9512         | CallBool true -> "True"
9513         | CallBool false -> "False"
9514       ) args
9515     )
9516   in
9517
9518   generate_lang_bindtests (
9519     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
9520   );
9521
9522   pr "  putStrLn \"EOF\"\n"
9523
9524 (* Language-independent bindings tests - we do it this way to
9525  * ensure there is parity in testing bindings across all languages.
9526  *)
9527 and generate_lang_bindtests call =
9528   call "test0" [CallString "abc"; CallOptString (Some "def");
9529                 CallStringList []; CallBool false;
9530                 CallInt 0; CallString "123"; CallString "456"];
9531   call "test0" [CallString "abc"; CallOptString None;
9532                 CallStringList []; CallBool false;
9533                 CallInt 0; CallString "123"; CallString "456"];
9534   call "test0" [CallString ""; CallOptString (Some "def");
9535                 CallStringList []; CallBool false;
9536                 CallInt 0; CallString "123"; CallString "456"];
9537   call "test0" [CallString ""; CallOptString (Some "");
9538                 CallStringList []; CallBool false;
9539                 CallInt 0; CallString "123"; CallString "456"];
9540   call "test0" [CallString "abc"; CallOptString (Some "def");
9541                 CallStringList ["1"]; CallBool false;
9542                 CallInt 0; CallString "123"; CallString "456"];
9543   call "test0" [CallString "abc"; CallOptString (Some "def");
9544                 CallStringList ["1"; "2"]; CallBool false;
9545                 CallInt 0; CallString "123"; CallString "456"];
9546   call "test0" [CallString "abc"; CallOptString (Some "def");
9547                 CallStringList ["1"]; CallBool true;
9548                 CallInt 0; CallString "123"; CallString "456"];
9549   call "test0" [CallString "abc"; CallOptString (Some "def");
9550                 CallStringList ["1"]; CallBool false;
9551                 CallInt (-1); CallString "123"; CallString "456"];
9552   call "test0" [CallString "abc"; CallOptString (Some "def");
9553                 CallStringList ["1"]; CallBool false;
9554                 CallInt (-2); CallString "123"; CallString "456"];
9555   call "test0" [CallString "abc"; CallOptString (Some "def");
9556                 CallStringList ["1"]; CallBool false;
9557                 CallInt 1; CallString "123"; CallString "456"];
9558   call "test0" [CallString "abc"; CallOptString (Some "def");
9559                 CallStringList ["1"]; CallBool false;
9560                 CallInt 2; CallString "123"; CallString "456"];
9561   call "test0" [CallString "abc"; CallOptString (Some "def");
9562                 CallStringList ["1"]; CallBool false;
9563                 CallInt 4095; CallString "123"; CallString "456"];
9564   call "test0" [CallString "abc"; CallOptString (Some "def");
9565                 CallStringList ["1"]; CallBool false;
9566                 CallInt 0; CallString ""; CallString ""]
9567
9568 (* XXX Add here tests of the return and error functions. *)
9569
9570 (* This is used to generate the src/MAX_PROC_NR file which
9571  * contains the maximum procedure number, a surrogate for the
9572  * ABI version number.  See src/Makefile.am for the details.
9573  *)
9574 and generate_max_proc_nr () =
9575   let proc_nrs = List.map (
9576     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
9577   ) daemon_functions in
9578
9579   let max_proc_nr = List.fold_left max 0 proc_nrs in
9580
9581   pr "%d\n" max_proc_nr
9582
9583 let output_to filename =
9584   let filename_new = filename ^ ".new" in
9585   chan := open_out filename_new;
9586   let close () =
9587     close_out !chan;
9588     chan := stdout;
9589
9590     (* Is the new file different from the current file? *)
9591     if Sys.file_exists filename && files_equal filename filename_new then
9592       Unix.unlink filename_new          (* same, so skip it *)
9593     else (
9594       (* different, overwrite old one *)
9595       (try Unix.chmod filename 0o644 with Unix.Unix_error _ -> ());
9596       Unix.rename filename_new filename;
9597       Unix.chmod filename 0o444;
9598       printf "written %s\n%!" filename;
9599     )
9600   in
9601   close
9602
9603 (* Main program. *)
9604 let () =
9605   check_functions ();
9606
9607   if not (Sys.file_exists "HACKING") then (
9608     eprintf "\
9609 You are probably running this from the wrong directory.
9610 Run it from the top source directory using the command
9611   src/generator.ml
9612 ";
9613     exit 1
9614   );
9615
9616   let close = output_to "src/guestfs_protocol.x" in
9617   generate_xdr ();
9618   close ();
9619
9620   let close = output_to "src/guestfs-structs.h" in
9621   generate_structs_h ();
9622   close ();
9623
9624   let close = output_to "src/guestfs-actions.h" in
9625   generate_actions_h ();
9626   close ();
9627
9628   let close = output_to "src/guestfs-internal-actions.h" in
9629   generate_internal_actions_h ();
9630   close ();
9631
9632   let close = output_to "src/guestfs-actions.c" in
9633   generate_client_actions ();
9634   close ();
9635
9636   let close = output_to "daemon/actions.h" in
9637   generate_daemon_actions_h ();
9638   close ();
9639
9640   let close = output_to "daemon/stubs.c" in
9641   generate_daemon_actions ();
9642   close ();
9643
9644   let close = output_to "daemon/names.c" in
9645   generate_daemon_names ();
9646   close ();
9647
9648   let close = output_to "capitests/tests.c" in
9649   generate_tests ();
9650   close ();
9651
9652   let close = output_to "src/guestfs-bindtests.c" in
9653   generate_bindtests ();
9654   close ();
9655
9656   let close = output_to "fish/cmds.c" in
9657   generate_fish_cmds ();
9658   close ();
9659
9660   let close = output_to "fish/completion.c" in
9661   generate_fish_completion ();
9662   close ();
9663
9664   let close = output_to "guestfs-structs.pod" in
9665   generate_structs_pod ();
9666   close ();
9667
9668   let close = output_to "guestfs-actions.pod" in
9669   generate_actions_pod ();
9670   close ();
9671
9672   let close = output_to "guestfish-actions.pod" in
9673   generate_fish_actions_pod ();
9674   close ();
9675
9676   let close = output_to "ocaml/guestfs.mli" in
9677   generate_ocaml_mli ();
9678   close ();
9679
9680   let close = output_to "ocaml/guestfs.ml" in
9681   generate_ocaml_ml ();
9682   close ();
9683
9684   let close = output_to "ocaml/guestfs_c_actions.c" in
9685   generate_ocaml_c ();
9686   close ();
9687
9688   let close = output_to "ocaml/bindtests.ml" in
9689   generate_ocaml_bindtests ();
9690   close ();
9691
9692   let close = output_to "perl/Guestfs.xs" in
9693   generate_perl_xs ();
9694   close ();
9695
9696   let close = output_to "perl/lib/Sys/Guestfs.pm" in
9697   generate_perl_pm ();
9698   close ();
9699
9700   let close = output_to "perl/bindtests.pl" in
9701   generate_perl_bindtests ();
9702   close ();
9703
9704   let close = output_to "python/guestfs-py.c" in
9705   generate_python_c ();
9706   close ();
9707
9708   let close = output_to "python/guestfs.py" in
9709   generate_python_py ();
9710   close ();
9711
9712   let close = output_to "python/bindtests.py" in
9713   generate_python_bindtests ();
9714   close ();
9715
9716   let close = output_to "ruby/ext/guestfs/_guestfs.c" in
9717   generate_ruby_c ();
9718   close ();
9719
9720   let close = output_to "ruby/bindtests.rb" in
9721   generate_ruby_bindtests ();
9722   close ();
9723
9724   let close = output_to "java/com/redhat/et/libguestfs/GuestFS.java" in
9725   generate_java_java ();
9726   close ();
9727
9728   List.iter (
9729     fun (typ, jtyp) ->
9730       let cols = cols_of_struct typ in
9731       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
9732       let close = output_to filename in
9733       generate_java_struct jtyp cols;
9734       close ();
9735   ) java_structs;
9736
9737   let close = output_to "java/Makefile.inc" in
9738   generate_java_makefile_inc ();
9739   close ();
9740
9741   let close = output_to "java/com_redhat_et_libguestfs_GuestFS.c" in
9742   generate_java_c ();
9743   close ();
9744
9745   let close = output_to "java/Bindtests.java" in
9746   generate_java_bindtests ();
9747   close ();
9748
9749   let close = output_to "haskell/Guestfs.hs" in
9750   generate_haskell_hs ();
9751   close ();
9752
9753   let close = output_to "haskell/Bindtests.hs" in
9754   generate_haskell_bindtests ();
9755   close ();
9756
9757   let close = output_to "src/MAX_PROC_NR" in
9758   generate_max_proc_nr ();
9759   close ();
9760
9761   (* Always generate this file last, and unconditionally.  It's used
9762    * by the Makefile to know when we must re-run the generator.
9763    *)
9764   let chan = open_out "src/stamp-generator" in
9765   fprintf chan "1\n";
9766   close_out chan