Documentation: lvcreate should say 'logical volume' (RHBZ#582953)
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 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 of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -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 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<val>.
1242
1243 In the Augeas API, it is possible to clear a node by setting
1244 the value to NULL.  Due to an oversight in the libguestfs API
1245 you cannot do that with this call.  Instead you must use the
1246 C<guestfs_aug_clear> call.");
1247
1248   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "insert a sibling Augeas node",
1251    "\
1252 Create a new sibling C<label> for C<path>, inserting it into
1253 the tree before or after C<path> (depending on the boolean
1254 flag C<before>).
1255
1256 C<path> must match exactly one existing node in the tree, and
1257 C<label> must be a label, ie. not contain C</>, C<*> or end
1258 with a bracketed index C<[N]>.");
1259
1260   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "remove an Augeas path",
1263    "\
1264 Remove C<path> and all of its children.
1265
1266 On success this returns the number of entries which were removed.");
1267
1268   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1269    [], (* XXX Augeas code needs tests. *)
1270    "move Augeas node",
1271    "\
1272 Move the node C<src> to C<dest>.  C<src> must match exactly
1273 one node.  C<dest> is overwritten if it exists.");
1274
1275   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "return Augeas nodes which match augpath",
1278    "\
1279 Returns a list of paths which match the path expression C<path>.
1280 The returned paths are sufficiently qualified so that they match
1281 exactly one node in the current tree.");
1282
1283   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1284    [], (* XXX Augeas code needs tests. *)
1285    "write all pending Augeas changes to disk",
1286    "\
1287 This writes all pending changes to disk.
1288
1289 The flags which were passed to C<guestfs_aug_init> affect exactly
1290 how files are saved.");
1291
1292   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1293    [], (* XXX Augeas code needs tests. *)
1294    "load files into the tree",
1295    "\
1296 Load files into the tree.
1297
1298 See C<aug_load> in the Augeas documentation for the full gory
1299 details.");
1300
1301   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1302    [], (* XXX Augeas code needs tests. *)
1303    "list Augeas nodes under augpath",
1304    "\
1305 This is just a shortcut for listing C<guestfs_aug_match>
1306 C<path/*> and sorting the resulting nodes into alphabetical order.");
1307
1308   ("rm", (RErr, [Pathname "path"]), 29, [],
1309    [InitBasicFS, Always, TestRun
1310       [["touch"; "/new"];
1311        ["rm"; "/new"]];
1312     InitBasicFS, Always, TestLastFail
1313       [["rm"; "/new"]];
1314     InitBasicFS, Always, TestLastFail
1315       [["mkdir"; "/new"];
1316        ["rm"; "/new"]]],
1317    "remove a file",
1318    "\
1319 Remove the single file C<path>.");
1320
1321   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1322    [InitBasicFS, Always, TestRun
1323       [["mkdir"; "/new"];
1324        ["rmdir"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["rmdir"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["touch"; "/new"];
1329        ["rmdir"; "/new"]]],
1330    "remove a directory",
1331    "\
1332 Remove the single directory C<path>.");
1333
1334   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1335    [InitBasicFS, Always, TestOutputFalse
1336       [["mkdir"; "/new"];
1337        ["mkdir"; "/new/foo"];
1338        ["touch"; "/new/foo/bar"];
1339        ["rm_rf"; "/new"];
1340        ["exists"; "/new"]]],
1341    "remove a file or directory recursively",
1342    "\
1343 Remove the file or directory C<path>, recursively removing the
1344 contents if its a directory.  This is like the C<rm -rf> shell
1345 command.");
1346
1347   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1348    [InitBasicFS, Always, TestOutputTrue
1349       [["mkdir"; "/new"];
1350        ["is_dir"; "/new"]];
1351     InitBasicFS, Always, TestLastFail
1352       [["mkdir"; "/new/foo/bar"]]],
1353    "create a directory",
1354    "\
1355 Create a directory named C<path>.");
1356
1357   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1358    [InitBasicFS, Always, TestOutputTrue
1359       [["mkdir_p"; "/new/foo/bar"];
1360        ["is_dir"; "/new/foo/bar"]];
1361     InitBasicFS, Always, TestOutputTrue
1362       [["mkdir_p"; "/new/foo/bar"];
1363        ["is_dir"; "/new/foo"]];
1364     InitBasicFS, Always, TestOutputTrue
1365       [["mkdir_p"; "/new/foo/bar"];
1366        ["is_dir"; "/new"]];
1367     (* Regression tests for RHBZ#503133: *)
1368     InitBasicFS, Always, TestRun
1369       [["mkdir"; "/new"];
1370        ["mkdir_p"; "/new"]];
1371     InitBasicFS, Always, TestLastFail
1372       [["touch"; "/new"];
1373        ["mkdir_p"; "/new"]]],
1374    "create a directory and parents",
1375    "\
1376 Create a directory named C<path>, creating any parent directories
1377 as necessary.  This is like the C<mkdir -p> shell command.");
1378
1379   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1380    [], (* XXX Need stat command to test *)
1381    "change file mode",
1382    "\
1383 Change the mode (permissions) of C<path> to C<mode>.  Only
1384 numeric modes are supported.
1385
1386 I<Note>: When using this command from guestfish, C<mode>
1387 by default would be decimal, unless you prefix it with
1388 C<0> to get octal, ie. use C<0700> not C<700>.");
1389
1390   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file owner and group",
1393    "\
1394 Change the file owner to C<owner> and group to C<group>.
1395
1396 Only numeric uid and gid are supported.  If you want to use
1397 names, you will need to locate and parse the password file
1398 yourself (Augeas support makes this relatively easy).");
1399
1400   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1401    [InitISOFS, Always, TestOutputTrue (
1402       [["exists"; "/empty"]]);
1403     InitISOFS, Always, TestOutputTrue (
1404       [["exists"; "/directory"]])],
1405    "test if file or directory exists",
1406    "\
1407 This returns C<true> if and only if there is a file, directory
1408 (or anything) with the given C<path> name.
1409
1410 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1411
1412   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1413    [InitISOFS, Always, TestOutputTrue (
1414       [["is_file"; "/known-1"]]);
1415     InitISOFS, Always, TestOutputFalse (
1416       [["is_file"; "/directory"]])],
1417    "test if file exists",
1418    "\
1419 This returns C<true> if and only if there is a file
1420 with the given C<path> name.  Note that it returns false for
1421 other objects like directories.
1422
1423 See also C<guestfs_stat>.");
1424
1425   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1426    [InitISOFS, Always, TestOutputFalse (
1427       [["is_dir"; "/known-3"]]);
1428     InitISOFS, Always, TestOutputTrue (
1429       [["is_dir"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a directory
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like files.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1439    [InitEmpty, Always, TestOutputListOfDevices (
1440       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1441        ["pvcreate"; "/dev/sda1"];
1442        ["pvcreate"; "/dev/sda2"];
1443        ["pvcreate"; "/dev/sda3"];
1444        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1445    "create an LVM physical volume",
1446    "\
1447 This creates an LVM physical volume on the named C<device>,
1448 where C<device> should usually be a partition name such
1449 as C</dev/sda1>.");
1450
1451   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputList (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1458        ["vgcreate"; "VG2"; "/dev/sda3"];
1459        ["vgs"]], ["VG1"; "VG2"])],
1460    "create an LVM volume group",
1461    "\
1462 This creates an LVM volume group called C<volgroup>
1463 from the non-empty list of physical volumes C<physvols>.");
1464
1465   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["lvcreate"; "LV1"; "VG1"; "50"];
1474        ["lvcreate"; "LV2"; "VG1"; "50"];
1475        ["lvcreate"; "LV3"; "VG2"; "50"];
1476        ["lvcreate"; "LV4"; "VG2"; "50"];
1477        ["lvcreate"; "LV5"; "VG2"; "50"];
1478        ["lvs"]],
1479       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1480        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1481    "create an LVM logical volume",
1482    "\
1483 This creates an LVM logical volume called C<logvol>
1484 on the volume group C<volgroup>, with C<size> megabytes.");
1485
1486   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1487    [InitEmpty, Always, TestOutput (
1488       [["part_disk"; "/dev/sda"; "mbr"];
1489        ["mkfs"; "ext2"; "/dev/sda1"];
1490        ["mount_options"; ""; "/dev/sda1"; "/"];
1491        ["write_file"; "/new"; "new file contents"; "0"];
1492        ["cat"; "/new"]], "new file contents")],
1493    "make a filesystem",
1494    "\
1495 This creates a filesystem on C<device> (usually a partition
1496 or LVM logical volume).  The filesystem type is C<fstype>, for
1497 example C<ext3>.");
1498
1499   ("sfdisk", (RErr, [Device "device";
1500                      Int "cyls"; Int "heads"; Int "sectors";
1501                      StringList "lines"]), 43, [DangerWillRobinson],
1502    [],
1503    "create partitions on a block device",
1504    "\
1505 This is a direct interface to the L<sfdisk(8)> program for creating
1506 partitions on block devices.
1507
1508 C<device> should be a block device, for example C</dev/sda>.
1509
1510 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1511 and sectors on the device, which are passed directly to sfdisk as
1512 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1513 of these, then the corresponding parameter is omitted.  Usually for
1514 'large' disks, you can just pass C<0> for these, but for small
1515 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1516 out the right geometry and you will need to tell it.
1517
1518 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1519 information refer to the L<sfdisk(8)> manpage.
1520
1521 To create a single partition occupying the whole disk, you would
1522 pass C<lines> as a single element list, when the single element being
1523 the string C<,> (comma).
1524
1525 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1526 C<guestfs_part_init>");
1527
1528   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1529    [InitBasicFS, Always, TestOutput (
1530       [["write_file"; "/new"; "new file contents"; "0"];
1531        ["cat"; "/new"]], "new file contents");
1532     InitBasicFS, Always, TestOutput (
1533       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1534        ["cat"; "/new"]], "\nnew file contents\n");
1535     InitBasicFS, Always, TestOutput (
1536       [["write_file"; "/new"; "\n\n"; "0"];
1537        ["cat"; "/new"]], "\n\n");
1538     InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; ""; "0"];
1540        ["cat"; "/new"]], "");
1541     InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "\n\n\n"; "0"];
1543        ["cat"; "/new"]], "\n\n\n");
1544     InitBasicFS, Always, TestOutput (
1545       [["write_file"; "/new"; "\n"; "0"];
1546        ["cat"; "/new"]], "\n")],
1547    "create a file",
1548    "\
1549 This call creates a file called C<path>.  The contents of the
1550 file is the string C<content> (which can contain any 8 bit data),
1551 with length C<size>.
1552
1553 As a special case, if C<size> is C<0>
1554 then the length is calculated using C<strlen> (so in this case
1555 the content cannot contain embedded ASCII NULs).
1556
1557 I<NB.> Owing to a bug, writing content containing ASCII NUL
1558 characters does I<not> work, even if the length is specified.
1559 We hope to resolve this bug in a future version.  In the meantime
1560 use C<guestfs_upload>.");
1561
1562   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1563    [InitEmpty, Always, TestOutputListOfDevices (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["mounts"]], ["/dev/sda1"]);
1568     InitEmpty, Always, TestOutputList (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["umount"; "/"];
1573        ["mounts"]], [])],
1574    "unmount a filesystem",
1575    "\
1576 This unmounts the given filesystem.  The filesystem may be
1577 specified either by its mountpoint (path) or the device which
1578 contains the filesystem.");
1579
1580   ("mounts", (RStringList "devices", []), 46, [],
1581    [InitBasicFS, Always, TestOutputListOfDevices (
1582       [["mounts"]], ["/dev/sda1"])],
1583    "show mounted filesystems",
1584    "\
1585 This returns the list of currently mounted filesystems.  It returns
1586 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1587
1588 Some internal mounts are not shown.
1589
1590 See also: C<guestfs_mountpoints>");
1591
1592   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1593    [InitBasicFS, Always, TestOutputList (
1594       [["umount_all"];
1595        ["mounts"]], []);
1596     (* check that umount_all can unmount nested mounts correctly: *)
1597     InitEmpty, Always, TestOutputList (
1598       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1599        ["mkfs"; "ext2"; "/dev/sda1"];
1600        ["mkfs"; "ext2"; "/dev/sda2"];
1601        ["mkfs"; "ext2"; "/dev/sda3"];
1602        ["mount_options"; ""; "/dev/sda1"; "/"];
1603        ["mkdir"; "/mp1"];
1604        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1605        ["mkdir"; "/mp1/mp2"];
1606        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1607        ["mkdir"; "/mp1/mp2/mp3"];
1608        ["umount_all"];
1609        ["mounts"]], [])],
1610    "unmount all filesystems",
1611    "\
1612 This unmounts all mounted filesystems.
1613
1614 Some internal mounts are not unmounted by this call.");
1615
1616   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1617    [],
1618    "remove all LVM LVs, VGs and PVs",
1619    "\
1620 This command removes all LVM logical volumes, volume groups
1621 and physical volumes.");
1622
1623   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1624    [InitISOFS, Always, TestOutput (
1625       [["file"; "/empty"]], "empty");
1626     InitISOFS, Always, TestOutput (
1627       [["file"; "/known-1"]], "ASCII text");
1628     InitISOFS, Always, TestLastFail (
1629       [["file"; "/notexists"]])],
1630    "determine file type",
1631    "\
1632 This call uses the standard L<file(1)> command to determine
1633 the type or contents of the file.  This also works on devices,
1634 for example to find out whether a partition contains a filesystem.
1635
1636 This call will also transparently look inside various types
1637 of compressed file.
1638
1639 The exact command which runs is C<file -zbsL path>.  Note in
1640 particular that the filename is not prepended to the output
1641 (the C<-b> option).");
1642
1643   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1644    [InitBasicFS, Always, TestOutput (
1645       [["upload"; "test-command"; "/test-command"];
1646        ["chmod"; "0o755"; "/test-command"];
1647        ["command"; "/test-command 1"]], "Result1");
1648     InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 2"]], "Result2\n");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 3"]], "\nResult3");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 4"]], "\nResult4\n");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 5"]], "\nResult5\n\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 7"]], "");
1672     InitBasicFS, Always, TestOutput (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command 8"]], "\n");
1676     InitBasicFS, Always, TestOutput (
1677       [["upload"; "test-command"; "/test-command"];
1678        ["chmod"; "0o755"; "/test-command"];
1679        ["command"; "/test-command 9"]], "\n\n");
1680     InitBasicFS, Always, TestOutput (
1681       [["upload"; "test-command"; "/test-command"];
1682        ["chmod"; "0o755"; "/test-command"];
1683        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1684     InitBasicFS, Always, TestOutput (
1685       [["upload"; "test-command"; "/test-command"];
1686        ["chmod"; "0o755"; "/test-command"];
1687        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1688     InitBasicFS, Always, TestLastFail (
1689       [["upload"; "test-command"; "/test-command"];
1690        ["chmod"; "0o755"; "/test-command"];
1691        ["command"; "/test-command"]])],
1692    "run a command from the guest filesystem",
1693    "\
1694 This call runs a command from the guest filesystem.  The
1695 filesystem must be mounted, and must contain a compatible
1696 operating system (ie. something Linux, with the same
1697 or compatible processor architecture).
1698
1699 The single parameter is an argv-style list of arguments.
1700 The first element is the name of the program to run.
1701 Subsequent elements are parameters.  The list must be
1702 non-empty (ie. must contain a program name).  Note that
1703 the command runs directly, and is I<not> invoked via
1704 the shell (see C<guestfs_sh>).
1705
1706 The return value is anything printed to I<stdout> by
1707 the command.
1708
1709 If the command returns a non-zero exit status, then
1710 this function returns an error message.  The error message
1711 string is the content of I<stderr> from the command.
1712
1713 The C<$PATH> environment variable will contain at least
1714 C</usr/bin> and C</bin>.  If you require a program from
1715 another location, you should provide the full path in the
1716 first parameter.
1717
1718 Shared libraries and data files required by the program
1719 must be available on filesystems which are mounted in the
1720 correct places.  It is the caller's responsibility to ensure
1721 all filesystems that are needed are mounted at the right
1722 locations.");
1723
1724   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1725    [InitBasicFS, Always, TestOutputList (
1726       [["upload"; "test-command"; "/test-command"];
1727        ["chmod"; "0o755"; "/test-command"];
1728        ["command_lines"; "/test-command 1"]], ["Result1"]);
1729     InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 2"]], ["Result2"]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 7"]], []);
1753     InitBasicFS, Always, TestOutputList (
1754       [["upload"; "test-command"; "/test-command"];
1755        ["chmod"; "0o755"; "/test-command"];
1756        ["command_lines"; "/test-command 8"]], [""]);
1757     InitBasicFS, Always, TestOutputList (
1758       [["upload"; "test-command"; "/test-command"];
1759        ["chmod"; "0o755"; "/test-command"];
1760        ["command_lines"; "/test-command 9"]], ["";""]);
1761     InitBasicFS, Always, TestOutputList (
1762       [["upload"; "test-command"; "/test-command"];
1763        ["chmod"; "0o755"; "/test-command"];
1764        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1765     InitBasicFS, Always, TestOutputList (
1766       [["upload"; "test-command"; "/test-command"];
1767        ["chmod"; "0o755"; "/test-command"];
1768        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1769    "run a command, returning lines",
1770    "\
1771 This is the same as C<guestfs_command>, but splits the
1772 result into a list of lines.
1773
1774 See also: C<guestfs_sh_lines>");
1775
1776   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1777    [InitISOFS, Always, TestOutputStruct (
1778       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1779    "get file information",
1780    "\
1781 Returns file information for the given C<path>.
1782
1783 This is the same as the C<stat(2)> system call.");
1784
1785   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1786    [InitISOFS, Always, TestOutputStruct (
1787       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1788    "get file information for a symbolic link",
1789    "\
1790 Returns file information for the given C<path>.
1791
1792 This is the same as C<guestfs_stat> except that if C<path>
1793 is a symbolic link, then the link is stat-ed, not the file it
1794 refers to.
1795
1796 This is the same as the C<lstat(2)> system call.");
1797
1798   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1799    [InitISOFS, Always, TestOutputStruct (
1800       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1801    "get file system statistics",
1802    "\
1803 Returns file system statistics for any mounted file system.
1804 C<path> should be a file or directory in the mounted file system
1805 (typically it is the mount point itself, but it doesn't need to be).
1806
1807 This is the same as the C<statvfs(2)> system call.");
1808
1809   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1810    [], (* XXX test *)
1811    "get ext2/ext3/ext4 superblock details",
1812    "\
1813 This returns the contents of the ext2, ext3 or ext4 filesystem
1814 superblock on C<device>.
1815
1816 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1817 manpage for more details.  The list of fields returned isn't
1818 clearly defined, and depends on both the version of C<tune2fs>
1819 that libguestfs was built against, and the filesystem itself.");
1820
1821   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1822    [InitEmpty, Always, TestOutputTrue (
1823       [["blockdev_setro"; "/dev/sda"];
1824        ["blockdev_getro"; "/dev/sda"]])],
1825    "set block device to read-only",
1826    "\
1827 Sets the block device named C<device> to read-only.
1828
1829 This uses the L<blockdev(8)> command.");
1830
1831   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1832    [InitEmpty, Always, TestOutputFalse (
1833       [["blockdev_setrw"; "/dev/sda"];
1834        ["blockdev_getro"; "/dev/sda"]])],
1835    "set block device to read-write",
1836    "\
1837 Sets the block device named C<device> to read-write.
1838
1839 This uses the L<blockdev(8)> command.");
1840
1841   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1842    [InitEmpty, Always, TestOutputTrue (
1843       [["blockdev_setro"; "/dev/sda"];
1844        ["blockdev_getro"; "/dev/sda"]])],
1845    "is block device set to read-only",
1846    "\
1847 Returns a boolean indicating if the block device is read-only
1848 (true if read-only, false if not).
1849
1850 This uses the L<blockdev(8)> command.");
1851
1852   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1853    [InitEmpty, Always, TestOutputInt (
1854       [["blockdev_getss"; "/dev/sda"]], 512)],
1855    "get sectorsize of block device",
1856    "\
1857 This returns the size of sectors on a block device.
1858 Usually 512, but can be larger for modern devices.
1859
1860 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1861 for that).
1862
1863 This uses the L<blockdev(8)> command.");
1864
1865   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1866    [InitEmpty, Always, TestOutputInt (
1867       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1868    "get blocksize of block device",
1869    "\
1870 This returns the block size of a device.
1871
1872 (Note this is different from both I<size in blocks> and
1873 I<filesystem block size>).
1874
1875 This uses the L<blockdev(8)> command.");
1876
1877   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1878    [], (* XXX test *)
1879    "set blocksize of block device",
1880    "\
1881 This sets the block size of a device.
1882
1883 (Note this is different from both I<size in blocks> and
1884 I<filesystem block size>).
1885
1886 This uses the L<blockdev(8)> command.");
1887
1888   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1889    [InitEmpty, Always, TestOutputInt (
1890       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1891    "get total size of device in 512-byte sectors",
1892    "\
1893 This returns the size of the device in units of 512-byte sectors
1894 (even if the sectorsize isn't 512 bytes ... weird).
1895
1896 See also C<guestfs_blockdev_getss> for the real sector size of
1897 the device, and C<guestfs_blockdev_getsize64> for the more
1898 useful I<size in bytes>.
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1905    "get total size of device in bytes",
1906    "\
1907 This returns the size of the device in bytes.
1908
1909 See also C<guestfs_blockdev_getsz>.
1910
1911 This uses the L<blockdev(8)> command.");
1912
1913   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1914    [InitEmpty, Always, TestRun
1915       [["blockdev_flushbufs"; "/dev/sda"]]],
1916    "flush device buffers",
1917    "\
1918 This tells the kernel to flush internal buffers associated
1919 with C<device>.
1920
1921 This uses the L<blockdev(8)> command.");
1922
1923   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1924    [InitEmpty, Always, TestRun
1925       [["blockdev_rereadpt"; "/dev/sda"]]],
1926    "reread partition table",
1927    "\
1928 Reread the partition table on C<device>.
1929
1930 This uses the L<blockdev(8)> command.");
1931
1932   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1933    [InitBasicFS, Always, TestOutput (
1934       (* Pick a file from cwd which isn't likely to change. *)
1935       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1936        ["checksum"; "md5"; "/COPYING.LIB"]],
1937       Digest.to_hex (Digest.file "COPYING.LIB"))],
1938    "upload a file from the local machine",
1939    "\
1940 Upload local file C<filename> to C<remotefilename> on the
1941 filesystem.
1942
1943 C<filename> can also be a named pipe.
1944
1945 See also C<guestfs_download>.");
1946
1947   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1948    [InitBasicFS, Always, TestOutput (
1949       (* Pick a file from cwd which isn't likely to change. *)
1950       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1951        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1952        ["upload"; "testdownload.tmp"; "/upload"];
1953        ["checksum"; "md5"; "/upload"]],
1954       Digest.to_hex (Digest.file "COPYING.LIB"))],
1955    "download a file to the local machine",
1956    "\
1957 Download file C<remotefilename> and save it as C<filename>
1958 on the local machine.
1959
1960 C<filename> can also be a named pipe.
1961
1962 See also C<guestfs_upload>, C<guestfs_cat>.");
1963
1964   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1965    [InitISOFS, Always, TestOutput (
1966       [["checksum"; "crc"; "/known-3"]], "2891671662");
1967     InitISOFS, Always, TestLastFail (
1968       [["checksum"; "crc"; "/notexists"]]);
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1979     InitISOFS, Always, TestOutput (
1980       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1981    "compute MD5, SHAx or CRC checksum of file",
1982    "\
1983 This call computes the MD5, SHAx or CRC checksum of the
1984 file named C<path>.
1985
1986 The type of checksum to compute is given by the C<csumtype>
1987 parameter which must have one of the following values:
1988
1989 =over 4
1990
1991 =item C<crc>
1992
1993 Compute the cyclic redundancy check (CRC) specified by POSIX
1994 for the C<cksum> command.
1995
1996 =item C<md5>
1997
1998 Compute the MD5 hash (using the C<md5sum> program).
1999
2000 =item C<sha1>
2001
2002 Compute the SHA1 hash (using the C<sha1sum> program).
2003
2004 =item C<sha224>
2005
2006 Compute the SHA224 hash (using the C<sha224sum> program).
2007
2008 =item C<sha256>
2009
2010 Compute the SHA256 hash (using the C<sha256sum> program).
2011
2012 =item C<sha384>
2013
2014 Compute the SHA384 hash (using the C<sha384sum> program).
2015
2016 =item C<sha512>
2017
2018 Compute the SHA512 hash (using the C<sha512sum> program).
2019
2020 =back
2021
2022 The checksum is returned as a printable string.");
2023
2024   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2025    [InitBasicFS, Always, TestOutput (
2026       [["tar_in"; "../images/helloworld.tar"; "/"];
2027        ["cat"; "/hello"]], "hello\n")],
2028    "unpack tarfile to directory",
2029    "\
2030 This command uploads and unpacks local file C<tarfile> (an
2031 I<uncompressed> tar file) into C<directory>.
2032
2033 To upload a compressed tarball, use C<guestfs_tgz_in>
2034 or C<guestfs_txz_in>.");
2035
2036   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2037    [],
2038    "pack directory into tarfile",
2039    "\
2040 This command packs the contents of C<directory> and downloads
2041 it to local file C<tarfile>.
2042
2043 To download a compressed tarball, use C<guestfs_tgz_out>
2044 or C<guestfs_txz_out>.");
2045
2046   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2047    [InitBasicFS, Always, TestOutput (
2048       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2049        ["cat"; "/hello"]], "hello\n")],
2050    "unpack compressed tarball to directory",
2051    "\
2052 This command uploads and unpacks local file C<tarball> (a
2053 I<gzip compressed> tar file) into C<directory>.
2054
2055 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2056
2057   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2058    [],
2059    "pack directory into compressed tarball",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarball>.
2063
2064 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2065
2066   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2067    [InitBasicFS, Always, TestLastFail (
2068       [["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["touch"; "/new"]]);
2071     InitBasicFS, Always, TestOutput (
2072       [["write_file"; "/new"; "data"; "0"];
2073        ["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["cat"; "/new"]], "data")],
2076    "mount a guest disk, read-only",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 mounts the filesystem with the read-only (I<-o ro>) flag.");
2080
2081   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2082    [],
2083    "mount a guest disk with mount options",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set the mount options as for the
2087 L<mount(8)> I<-o> flag.");
2088
2089   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2090    [],
2091    "mount a guest disk with mount options and vfstype",
2092    "\
2093 This is the same as the C<guestfs_mount> command, but it
2094 allows you to set both the mount options and the vfstype
2095 as for the L<mount(8)> I<-o> and I<-t> flags.");
2096
2097   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2098    [],
2099    "debugging and internals",
2100    "\
2101 The C<guestfs_debug> command exposes some internals of
2102 C<guestfsd> (the guestfs daemon) that runs inside the
2103 qemu subprocess.
2104
2105 There is no comprehensive help for this command.  You have
2106 to look at the file C<daemon/debug.c> in the libguestfs source
2107 to find out what you can do.");
2108
2109   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2110    [InitEmpty, Always, TestOutputList (
2111       [["part_disk"; "/dev/sda"; "mbr"];
2112        ["pvcreate"; "/dev/sda1"];
2113        ["vgcreate"; "VG"; "/dev/sda1"];
2114        ["lvcreate"; "LV1"; "VG"; "50"];
2115        ["lvcreate"; "LV2"; "VG"; "50"];
2116        ["lvremove"; "/dev/VG/LV1"];
2117        ["lvs"]], ["/dev/VG/LV2"]);
2118     InitEmpty, Always, TestOutputList (
2119       [["part_disk"; "/dev/sda"; "mbr"];
2120        ["pvcreate"; "/dev/sda1"];
2121        ["vgcreate"; "VG"; "/dev/sda1"];
2122        ["lvcreate"; "LV1"; "VG"; "50"];
2123        ["lvcreate"; "LV2"; "VG"; "50"];
2124        ["lvremove"; "/dev/VG"];
2125        ["lvs"]], []);
2126     InitEmpty, Always, TestOutputList (
2127       [["part_disk"; "/dev/sda"; "mbr"];
2128        ["pvcreate"; "/dev/sda1"];
2129        ["vgcreate"; "VG"; "/dev/sda1"];
2130        ["lvcreate"; "LV1"; "VG"; "50"];
2131        ["lvcreate"; "LV2"; "VG"; "50"];
2132        ["lvremove"; "/dev/VG"];
2133        ["vgs"]], ["VG"])],
2134    "remove an LVM logical volume",
2135    "\
2136 Remove an LVM logical volume C<device>, where C<device> is
2137 the path to the LV, such as C</dev/VG/LV>.
2138
2139 You can also remove all LVs in a volume group by specifying
2140 the VG name, C</dev/VG>.");
2141
2142   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2143    [InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["vgremove"; "VG"];
2150        ["lvs"]], []);
2151     InitEmpty, Always, TestOutputList (
2152       [["part_disk"; "/dev/sda"; "mbr"];
2153        ["pvcreate"; "/dev/sda1"];
2154        ["vgcreate"; "VG"; "/dev/sda1"];
2155        ["lvcreate"; "LV1"; "VG"; "50"];
2156        ["lvcreate"; "LV2"; "VG"; "50"];
2157        ["vgremove"; "VG"];
2158        ["vgs"]], [])],
2159    "remove an LVM volume group",
2160    "\
2161 Remove an LVM volume group C<vgname>, (for example C<VG>).
2162
2163 This also forcibly removes all logical volumes in the volume
2164 group (if any).");
2165
2166   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2167    [InitEmpty, Always, TestOutputListOfDevices (
2168       [["part_disk"; "/dev/sda"; "mbr"];
2169        ["pvcreate"; "/dev/sda1"];
2170        ["vgcreate"; "VG"; "/dev/sda1"];
2171        ["lvcreate"; "LV1"; "VG"; "50"];
2172        ["lvcreate"; "LV2"; "VG"; "50"];
2173        ["vgremove"; "VG"];
2174        ["pvremove"; "/dev/sda1"];
2175        ["lvs"]], []);
2176     InitEmpty, Always, TestOutputListOfDevices (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["pvremove"; "/dev/sda1"];
2184        ["vgs"]], []);
2185     InitEmpty, Always, TestOutputListOfDevices (
2186       [["part_disk"; "/dev/sda"; "mbr"];
2187        ["pvcreate"; "/dev/sda1"];
2188        ["vgcreate"; "VG"; "/dev/sda1"];
2189        ["lvcreate"; "LV1"; "VG"; "50"];
2190        ["lvcreate"; "LV2"; "VG"; "50"];
2191        ["vgremove"; "VG"];
2192        ["pvremove"; "/dev/sda1"];
2193        ["pvs"]], [])],
2194    "remove an LVM physical volume",
2195    "\
2196 This wipes a physical volume C<device> so that LVM will no longer
2197 recognise it.
2198
2199 The implementation uses the C<pvremove> command which refuses to
2200 wipe physical volumes that contain any volume groups, so you have
2201 to remove those first.");
2202
2203   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2204    [InitBasicFS, Always, TestOutput (
2205       [["set_e2label"; "/dev/sda1"; "testlabel"];
2206        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2207    "set the ext2/3/4 filesystem label",
2208    "\
2209 This sets the ext2/3/4 filesystem label of the filesystem on
2210 C<device> to C<label>.  Filesystem labels are limited to
2211 16 characters.
2212
2213 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2214 to return the existing label on a filesystem.");
2215
2216   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2217    [],
2218    "get the ext2/3/4 filesystem label",
2219    "\
2220 This returns the ext2/3/4 filesystem label of the filesystem on
2221 C<device>.");
2222
2223   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2224    (let uuid = uuidgen () in
2225     [InitBasicFS, Always, TestOutput (
2226        [["set_e2uuid"; "/dev/sda1"; uuid];
2227         ["get_e2uuid"; "/dev/sda1"]], uuid);
2228      InitBasicFS, Always, TestOutput (
2229        [["set_e2uuid"; "/dev/sda1"; "clear"];
2230         ["get_e2uuid"; "/dev/sda1"]], "");
2231      (* We can't predict what UUIDs will be, so just check the commands run. *)
2232      InitBasicFS, Always, TestRun (
2233        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2234      InitBasicFS, Always, TestRun (
2235        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2236    "set the ext2/3/4 filesystem UUID",
2237    "\
2238 This sets the ext2/3/4 filesystem UUID of the filesystem on
2239 C<device> to C<uuid>.  The format of the UUID and alternatives
2240 such as C<clear>, C<random> and C<time> are described in the
2241 L<tune2fs(8)> manpage.
2242
2243 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2244 to return the existing UUID of a filesystem.");
2245
2246   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2247    [],
2248    "get the ext2/3/4 filesystem UUID",
2249    "\
2250 This returns the ext2/3/4 filesystem UUID of the filesystem on
2251 C<device>.");
2252
2253   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2254    [InitBasicFS, Always, TestOutputInt (
2255       [["umount"; "/dev/sda1"];
2256        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2257     InitBasicFS, Always, TestOutputInt (
2258       [["umount"; "/dev/sda1"];
2259        ["zero"; "/dev/sda1"];
2260        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2261    "run the filesystem checker",
2262    "\
2263 This runs the filesystem checker (fsck) on C<device> which
2264 should have filesystem type C<fstype>.
2265
2266 The returned integer is the status.  See L<fsck(8)> for the
2267 list of status codes from C<fsck>.
2268
2269 Notes:
2270
2271 =over 4
2272
2273 =item *
2274
2275 Multiple status codes can be summed together.
2276
2277 =item *
2278
2279 A non-zero return code can mean \"success\", for example if
2280 errors have been corrected on the filesystem.
2281
2282 =item *
2283
2284 Checking or repairing NTFS volumes is not supported
2285 (by linux-ntfs).
2286
2287 =back
2288
2289 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2290
2291   ("zero", (RErr, [Device "device"]), 85, [],
2292    [InitBasicFS, Always, TestOutput (
2293       [["umount"; "/dev/sda1"];
2294        ["zero"; "/dev/sda1"];
2295        ["file"; "/dev/sda1"]], "data")],
2296    "write zeroes to the device",
2297    "\
2298 This command writes zeroes over the first few blocks of C<device>.
2299
2300 How many blocks are zeroed isn't specified (but it's I<not> enough
2301 to securely wipe the device).  It should be sufficient to remove
2302 any partition tables, filesystem superblocks and so on.
2303
2304 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2305
2306   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2307    (* Test disabled because grub-install incompatible with virtio-blk driver.
2308     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2309     *)
2310    [InitBasicFS, Disabled, TestOutputTrue (
2311       [["grub_install"; "/"; "/dev/sda1"];
2312        ["is_dir"; "/boot"]])],
2313    "install GRUB",
2314    "\
2315 This command installs GRUB (the Grand Unified Bootloader) on
2316 C<device>, with the root directory being C<root>.");
2317
2318   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2319    [InitBasicFS, Always, TestOutput (
2320       [["write_file"; "/old"; "file content"; "0"];
2321        ["cp"; "/old"; "/new"];
2322        ["cat"; "/new"]], "file content");
2323     InitBasicFS, Always, TestOutputTrue (
2324       [["write_file"; "/old"; "file content"; "0"];
2325        ["cp"; "/old"; "/new"];
2326        ["is_file"; "/old"]]);
2327     InitBasicFS, Always, TestOutput (
2328       [["write_file"; "/old"; "file content"; "0"];
2329        ["mkdir"; "/dir"];
2330        ["cp"; "/old"; "/dir/new"];
2331        ["cat"; "/dir/new"]], "file content")],
2332    "copy a file",
2333    "\
2334 This copies a file from C<src> to C<dest> where C<dest> is
2335 either a destination filename or destination directory.");
2336
2337   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2338    [InitBasicFS, Always, TestOutput (
2339       [["mkdir"; "/olddir"];
2340        ["mkdir"; "/newdir"];
2341        ["write_file"; "/olddir/file"; "file content"; "0"];
2342        ["cp_a"; "/olddir"; "/newdir"];
2343        ["cat"; "/newdir/olddir/file"]], "file content")],
2344    "copy a file or directory recursively",
2345    "\
2346 This copies a file or directory from C<src> to C<dest>
2347 recursively using the C<cp -a> command.");
2348
2349   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2350    [InitBasicFS, Always, TestOutput (
2351       [["write_file"; "/old"; "file content"; "0"];
2352        ["mv"; "/old"; "/new"];
2353        ["cat"; "/new"]], "file content");
2354     InitBasicFS, Always, TestOutputFalse (
2355       [["write_file"; "/old"; "file content"; "0"];
2356        ["mv"; "/old"; "/new"];
2357        ["is_file"; "/old"]])],
2358    "move a file",
2359    "\
2360 This moves a file from C<src> to C<dest> where C<dest> is
2361 either a destination filename or destination directory.");
2362
2363   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2364    [InitEmpty, Always, TestRun (
2365       [["drop_caches"; "3"]])],
2366    "drop kernel page cache, dentries and inodes",
2367    "\
2368 This instructs the guest kernel to drop its page cache,
2369 and/or dentries and inode caches.  The parameter C<whattodrop>
2370 tells the kernel what precisely to drop, see
2371 L<http://linux-mm.org/Drop_Caches>
2372
2373 Setting C<whattodrop> to 3 should drop everything.
2374
2375 This automatically calls L<sync(2)> before the operation,
2376 so that the maximum guest memory is freed.");
2377
2378   ("dmesg", (RString "kmsgs", []), 91, [],
2379    [InitEmpty, Always, TestRun (
2380       [["dmesg"]])],
2381    "return kernel messages",
2382    "\
2383 This returns the kernel messages (C<dmesg> output) from
2384 the guest kernel.  This is sometimes useful for extended
2385 debugging of problems.
2386
2387 Another way to get the same information is to enable
2388 verbose messages with C<guestfs_set_verbose> or by setting
2389 the environment variable C<LIBGUESTFS_DEBUG=1> before
2390 running the program.");
2391
2392   ("ping_daemon", (RErr, []), 92, [],
2393    [InitEmpty, Always, TestRun (
2394       [["ping_daemon"]])],
2395    "ping the guest daemon",
2396    "\
2397 This is a test probe into the guestfs daemon running inside
2398 the qemu subprocess.  Calling this function checks that the
2399 daemon responds to the ping message, without affecting the daemon
2400 or attached block device(s) in any other way.");
2401
2402   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2403    [InitBasicFS, Always, TestOutputTrue (
2404       [["write_file"; "/file1"; "contents of a file"; "0"];
2405        ["cp"; "/file1"; "/file2"];
2406        ["equal"; "/file1"; "/file2"]]);
2407     InitBasicFS, Always, TestOutputFalse (
2408       [["write_file"; "/file1"; "contents of a file"; "0"];
2409        ["write_file"; "/file2"; "contents of another file"; "0"];
2410        ["equal"; "/file1"; "/file2"]]);
2411     InitBasicFS, Always, TestLastFail (
2412       [["equal"; "/file1"; "/file2"]])],
2413    "test if two files have equal contents",
2414    "\
2415 This compares the two files C<file1> and C<file2> and returns
2416 true if their content is exactly equal, or false otherwise.
2417
2418 The external L<cmp(1)> program is used for the comparison.");
2419
2420   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2421    [InitISOFS, Always, TestOutputList (
2422       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2423     InitISOFS, Always, TestOutputList (
2424       [["strings"; "/empty"]], [])],
2425    "print the printable strings in a file",
2426    "\
2427 This runs the L<strings(1)> command on a file and returns
2428 the list of printable strings found.");
2429
2430   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2431    [InitISOFS, Always, TestOutputList (
2432       [["strings_e"; "b"; "/known-5"]], []);
2433     InitBasicFS, Disabled, TestOutputList (
2434       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2435        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2436    "print the printable strings in a file",
2437    "\
2438 This is like the C<guestfs_strings> command, but allows you to
2439 specify the encoding.
2440
2441 See the L<strings(1)> manpage for the full list of encodings.
2442
2443 Commonly useful encodings are C<l> (lower case L) which will
2444 show strings inside Windows/x86 files.
2445
2446 The returned strings are transcoded to UTF-8.");
2447
2448   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2449    [InitISOFS, Always, TestOutput (
2450       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2451     (* Test for RHBZ#501888c2 regression which caused large hexdump
2452      * commands to segfault.
2453      *)
2454     InitISOFS, Always, TestRun (
2455       [["hexdump"; "/100krandom"]])],
2456    "dump a file in hexadecimal",
2457    "\
2458 This runs C<hexdump -C> on the given C<path>.  The result is
2459 the human-readable, canonical hex dump of the file.");
2460
2461   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2462    [InitNone, Always, TestOutput (
2463       [["part_disk"; "/dev/sda"; "mbr"];
2464        ["mkfs"; "ext3"; "/dev/sda1"];
2465        ["mount_options"; ""; "/dev/sda1"; "/"];
2466        ["write_file"; "/new"; "test file"; "0"];
2467        ["umount"; "/dev/sda1"];
2468        ["zerofree"; "/dev/sda1"];
2469        ["mount_options"; ""; "/dev/sda1"; "/"];
2470        ["cat"; "/new"]], "test file")],
2471    "zero unused inodes and disk blocks on ext2/3 filesystem",
2472    "\
2473 This runs the I<zerofree> program on C<device>.  This program
2474 claims to zero unused inodes and disk blocks on an ext2/3
2475 filesystem, thus making it possible to compress the filesystem
2476 more effectively.
2477
2478 You should B<not> run this program if the filesystem is
2479 mounted.
2480
2481 It is possible that using this program can damage the filesystem
2482 or data on the filesystem.");
2483
2484   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2485    [],
2486    "resize an LVM physical volume",
2487    "\
2488 This resizes (expands or shrinks) an existing LVM physical
2489 volume to match the new size of the underlying device.");
2490
2491   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2492                        Int "cyls"; Int "heads"; Int "sectors";
2493                        String "line"]), 99, [DangerWillRobinson],
2494    [],
2495    "modify a single partition on a block device",
2496    "\
2497 This runs L<sfdisk(8)> option to modify just the single
2498 partition C<n> (note: C<n> counts from 1).
2499
2500 For other parameters, see C<guestfs_sfdisk>.  You should usually
2501 pass C<0> for the cyls/heads/sectors parameters.
2502
2503 See also: C<guestfs_part_add>");
2504
2505   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2506    [],
2507    "display the partition table",
2508    "\
2509 This displays the partition table on C<device>, in the
2510 human-readable output of the L<sfdisk(8)> command.  It is
2511 not intended to be parsed.
2512
2513 See also: C<guestfs_part_list>");
2514
2515   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2516    [],
2517    "display the kernel geometry",
2518    "\
2519 This displays the kernel's idea of the geometry of C<device>.
2520
2521 The result is in human-readable format, and not designed to
2522 be parsed.");
2523
2524   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2525    [],
2526    "display the disk geometry from the partition table",
2527    "\
2528 This displays the disk geometry of C<device> read from the
2529 partition table.  Especially in the case where the underlying
2530 block device has been resized, this can be different from the
2531 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2532
2533 The result is in human-readable format, and not designed to
2534 be parsed.");
2535
2536   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2537    [],
2538    "activate or deactivate all volume groups",
2539    "\
2540 This command activates or (if C<activate> is false) deactivates
2541 all logical volumes in all volume groups.
2542 If activated, then they are made known to the
2543 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2544 then those devices disappear.
2545
2546 This command is the same as running C<vgchange -a y|n>");
2547
2548   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2549    [],
2550    "activate or deactivate some volume groups",
2551    "\
2552 This command activates or (if C<activate> is false) deactivates
2553 all logical volumes in the listed volume groups C<volgroups>.
2554 If activated, then they are made known to the
2555 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2556 then those devices disappear.
2557
2558 This command is the same as running C<vgchange -a y|n volgroups...>
2559
2560 Note that if C<volgroups> is an empty list then B<all> volume groups
2561 are activated or deactivated.");
2562
2563   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2564    [InitNone, Always, TestOutput (
2565       [["part_disk"; "/dev/sda"; "mbr"];
2566        ["pvcreate"; "/dev/sda1"];
2567        ["vgcreate"; "VG"; "/dev/sda1"];
2568        ["lvcreate"; "LV"; "VG"; "10"];
2569        ["mkfs"; "ext2"; "/dev/VG/LV"];
2570        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2571        ["write_file"; "/new"; "test content"; "0"];
2572        ["umount"; "/"];
2573        ["lvresize"; "/dev/VG/LV"; "20"];
2574        ["e2fsck_f"; "/dev/VG/LV"];
2575        ["resize2fs"; "/dev/VG/LV"];
2576        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2577        ["cat"; "/new"]], "test content")],
2578    "resize an LVM logical volume",
2579    "\
2580 This resizes (expands or shrinks) an existing LVM logical
2581 volume to C<mbytes>.  When reducing, data in the reduced part
2582 is lost.");
2583
2584   ("resize2fs", (RErr, [Device "device"]), 106, [],
2585    [], (* lvresize tests this *)
2586    "resize an ext2/ext3 filesystem",
2587    "\
2588 This resizes an ext2 or ext3 filesystem to match the size of
2589 the underlying device.
2590
2591 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2592 on the C<device> before calling this command.  For unknown reasons
2593 C<resize2fs> sometimes gives an error about this and sometimes not.
2594 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2595 calling this function.");
2596
2597   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2598    [InitBasicFS, Always, TestOutputList (
2599       [["find"; "/"]], ["lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["touch"; "/a"];
2602        ["mkdir"; "/b"];
2603        ["touch"; "/b/c"];
2604        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2605     InitBasicFS, Always, TestOutputList (
2606       [["mkdir_p"; "/a/b/c"];
2607        ["touch"; "/a/b/c/d"];
2608        ["find"; "/a/b/"]], ["c"; "c/d"])],
2609    "find all files and directories",
2610    "\
2611 This command lists out all files and directories, recursively,
2612 starting at C<directory>.  It is essentially equivalent to
2613 running the shell command C<find directory -print> but some
2614 post-processing happens on the output, described below.
2615
2616 This returns a list of strings I<without any prefix>.  Thus
2617 if the directory structure was:
2618
2619  /tmp/a
2620  /tmp/b
2621  /tmp/c/d
2622
2623 then the returned list from C<guestfs_find> C</tmp> would be
2624 4 elements:
2625
2626  a
2627  b
2628  c
2629  c/d
2630
2631 If C<directory> is not a directory, then this command returns
2632 an error.
2633
2634 The returned list is sorted.
2635
2636 See also C<guestfs_find0>.");
2637
2638   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2639    [], (* lvresize tests this *)
2640    "check an ext2/ext3 filesystem",
2641    "\
2642 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2643 filesystem checker on C<device>, noninteractively (C<-p>),
2644 even if the filesystem appears to be clean (C<-f>).
2645
2646 This command is only needed because of C<guestfs_resize2fs>
2647 (q.v.).  Normally you should use C<guestfs_fsck>.");
2648
2649   ("sleep", (RErr, [Int "secs"]), 109, [],
2650    [InitNone, Always, TestRun (
2651       [["sleep"; "1"]])],
2652    "sleep for some seconds",
2653    "\
2654 Sleep for C<secs> seconds.");
2655
2656   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2657    [InitNone, Always, TestOutputInt (
2658       [["part_disk"; "/dev/sda"; "mbr"];
2659        ["mkfs"; "ntfs"; "/dev/sda1"];
2660        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2661     InitNone, Always, TestOutputInt (
2662       [["part_disk"; "/dev/sda"; "mbr"];
2663        ["mkfs"; "ext2"; "/dev/sda1"];
2664        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2665    "probe NTFS volume",
2666    "\
2667 This command runs the L<ntfs-3g.probe(8)> command which probes
2668 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2669 be mounted read-write, and some cannot be mounted at all).
2670
2671 C<rw> is a boolean flag.  Set it to true if you want to test
2672 if the volume can be mounted read-write.  Set it to false if
2673 you want to test if the volume can be mounted read-only.
2674
2675 The return value is an integer which C<0> if the operation
2676 would succeed, or some non-zero value documented in the
2677 L<ntfs-3g.probe(8)> manual page.");
2678
2679   ("sh", (RString "output", [String "command"]), 111, [],
2680    [], (* XXX needs tests *)
2681    "run a command via the shell",
2682    "\
2683 This call runs a command from the guest filesystem via the
2684 guest's C</bin/sh>.
2685
2686 This is like C<guestfs_command>, but passes the command to:
2687
2688  /bin/sh -c \"command\"
2689
2690 Depending on the guest's shell, this usually results in
2691 wildcards being expanded, shell expressions being interpolated
2692 and so on.
2693
2694 All the provisos about C<guestfs_command> apply to this call.");
2695
2696   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2697    [], (* XXX needs tests *)
2698    "run a command via the shell returning lines",
2699    "\
2700 This is the same as C<guestfs_sh>, but splits the result
2701 into a list of lines.
2702
2703 See also: C<guestfs_command_lines>");
2704
2705   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2706    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2707     * code in stubs.c, since all valid glob patterns must start with "/".
2708     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2709     *)
2710    [InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2720     InitBasicFS, Always, TestOutputList (
2721       [["mkdir_p"; "/a/b/c"];
2722        ["touch"; "/a/b/c/d"];
2723        ["touch"; "/a/b/c/e"];
2724        ["glob_expand"; "/a/*/x/*"]], [])],
2725    "expand a wildcard path",
2726    "\
2727 This command searches for all the pathnames matching
2728 C<pattern> according to the wildcard expansion rules
2729 used by the shell.
2730
2731 If no paths match, then this returns an empty list
2732 (note: not an error).
2733
2734 It is just a wrapper around the C L<glob(3)> function
2735 with flags C<GLOB_MARK|GLOB_BRACE>.
2736 See that manual page for more details.");
2737
2738   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2739    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2740       [["scrub_device"; "/dev/sdc"]])],
2741    "scrub (securely wipe) a device",
2742    "\
2743 This command writes patterns over C<device> to make data retrieval
2744 more difficult.
2745
2746 It is an interface to the L<scrub(1)> program.  See that
2747 manual page for more details.");
2748
2749   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2750    [InitBasicFS, Always, TestRun (
2751       [["write_file"; "/file"; "content"; "0"];
2752        ["scrub_file"; "/file"]])],
2753    "scrub (securely wipe) a file",
2754    "\
2755 This command writes patterns over a file to make data retrieval
2756 more difficult.
2757
2758 The file is I<removed> after scrubbing.
2759
2760 It is an interface to the L<scrub(1)> program.  See that
2761 manual page for more details.");
2762
2763   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2764    [], (* XXX needs testing *)
2765    "scrub (securely wipe) free space",
2766    "\
2767 This command creates the directory C<dir> and then fills it
2768 with files until the filesystem is full, and scrubs the files
2769 as for C<guestfs_scrub_file>, and deletes them.
2770 The intention is to scrub any free space on the partition
2771 containing C<dir>.
2772
2773 It is an interface to the L<scrub(1)> program.  See that
2774 manual page for more details.");
2775
2776   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2777    [InitBasicFS, Always, TestRun (
2778       [["mkdir"; "/tmp"];
2779        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2780    "create a temporary directory",
2781    "\
2782 This command creates a temporary directory.  The
2783 C<template> parameter should be a full pathname for the
2784 temporary directory name with the final six characters being
2785 \"XXXXXX\".
2786
2787 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2788 the second one being suitable for Windows filesystems.
2789
2790 The name of the temporary directory that was created
2791 is returned.
2792
2793 The temporary directory is created with mode 0700
2794 and is owned by root.
2795
2796 The caller is responsible for deleting the temporary
2797 directory and its contents after use.
2798
2799 See also: L<mkdtemp(3)>");
2800
2801   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2802    [InitISOFS, Always, TestOutputInt (
2803       [["wc_l"; "/10klines"]], 10000)],
2804    "count lines in a file",
2805    "\
2806 This command counts the lines in a file, using the
2807 C<wc -l> external command.");
2808
2809   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2810    [InitISOFS, Always, TestOutputInt (
2811       [["wc_w"; "/10klines"]], 10000)],
2812    "count words in a file",
2813    "\
2814 This command counts the words in a file, using the
2815 C<wc -w> external command.");
2816
2817   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2818    [InitISOFS, Always, TestOutputInt (
2819       [["wc_c"; "/100kallspaces"]], 102400)],
2820    "count characters in a file",
2821    "\
2822 This command counts the characters in a file, using the
2823 C<wc -c> external command.");
2824
2825   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2826    [InitISOFS, Always, TestOutputList (
2827       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2828    "return first 10 lines of a file",
2829    "\
2830 This command returns up to the first 10 lines of a file as
2831 a list of strings.");
2832
2833   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2834    [InitISOFS, Always, TestOutputList (
2835       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2836     InitISOFS, Always, TestOutputList (
2837       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2838     InitISOFS, Always, TestOutputList (
2839       [["head_n"; "0"; "/10klines"]], [])],
2840    "return first N lines of a file",
2841    "\
2842 If the parameter C<nrlines> is a positive number, this returns the first
2843 C<nrlines> lines of the file C<path>.
2844
2845 If the parameter C<nrlines> is a negative number, this returns lines
2846 from the file C<path>, excluding the last C<nrlines> lines.
2847
2848 If the parameter C<nrlines> is zero, this returns an empty list.");
2849
2850   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2851    [InitISOFS, Always, TestOutputList (
2852       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2853    "return last 10 lines of a file",
2854    "\
2855 This command returns up to the last 10 lines of a file as
2856 a list of strings.");
2857
2858   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2859    [InitISOFS, Always, TestOutputList (
2860       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2861     InitISOFS, Always, TestOutputList (
2862       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2863     InitISOFS, Always, TestOutputList (
2864       [["tail_n"; "0"; "/10klines"]], [])],
2865    "return last N lines of a file",
2866    "\
2867 If the parameter C<nrlines> is a positive number, this returns the last
2868 C<nrlines> lines of the file C<path>.
2869
2870 If the parameter C<nrlines> is a negative number, this returns lines
2871 from the file C<path>, starting with the C<-nrlines>th line.
2872
2873 If the parameter C<nrlines> is zero, this returns an empty list.");
2874
2875   ("df", (RString "output", []), 125, [],
2876    [], (* XXX Tricky to test because it depends on the exact format
2877         * of the 'df' command and other imponderables.
2878         *)
2879    "report file system disk space usage",
2880    "\
2881 This command runs the C<df> command to report disk space used.
2882
2883 This command is mostly useful for interactive sessions.  It
2884 is I<not> intended that you try to parse the output string.
2885 Use C<statvfs> from programs.");
2886
2887   ("df_h", (RString "output", []), 126, [],
2888    [], (* XXX Tricky to test because it depends on the exact format
2889         * of the 'df' command and other imponderables.
2890         *)
2891    "report file system disk space usage (human readable)",
2892    "\
2893 This command runs the C<df -h> command to report disk space used
2894 in human-readable format.
2895
2896 This command is mostly useful for interactive sessions.  It
2897 is I<not> intended that you try to parse the output string.
2898 Use C<statvfs> from programs.");
2899
2900   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2901    [InitISOFS, Always, TestOutputInt (
2902       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2903    "estimate file space usage",
2904    "\
2905 This command runs the C<du -s> command to estimate file space
2906 usage for C<path>.
2907
2908 C<path> can be a file or a directory.  If C<path> is a directory
2909 then the estimate includes the contents of the directory and all
2910 subdirectories (recursively).
2911
2912 The result is the estimated size in I<kilobytes>
2913 (ie. units of 1024 bytes).");
2914
2915   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2916    [InitISOFS, Always, TestOutputList (
2917       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2918    "list files in an initrd",
2919    "\
2920 This command lists out files contained in an initrd.
2921
2922 The files are listed without any initial C</> character.  The
2923 files are listed in the order they appear (not necessarily
2924 alphabetical).  Directory names are listed as separate items.
2925
2926 Old Linux kernels (2.4 and earlier) used a compressed ext2
2927 filesystem as initrd.  We I<only> support the newer initramfs
2928 format (compressed cpio files).");
2929
2930   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2931    [],
2932    "mount a file using the loop device",
2933    "\
2934 This command lets you mount C<file> (a filesystem image
2935 in a file) on a mount point.  It is entirely equivalent to
2936 the command C<mount -o loop file mountpoint>.");
2937
2938   ("mkswap", (RErr, [Device "device"]), 130, [],
2939    [InitEmpty, Always, TestRun (
2940       [["part_disk"; "/dev/sda"; "mbr"];
2941        ["mkswap"; "/dev/sda1"]])],
2942    "create a swap partition",
2943    "\
2944 Create a swap partition on C<device>.");
2945
2946   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2947    [InitEmpty, Always, TestRun (
2948       [["part_disk"; "/dev/sda"; "mbr"];
2949        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2950    "create a swap partition with a label",
2951    "\
2952 Create a swap partition on C<device> with label C<label>.
2953
2954 Note that you cannot attach a swap label to a block device
2955 (eg. C</dev/sda>), just to a partition.  This appears to be
2956 a limitation of the kernel or swap tools.");
2957
2958   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2959    (let uuid = uuidgen () in
2960     [InitEmpty, Always, TestRun (
2961        [["part_disk"; "/dev/sda"; "mbr"];
2962         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2963    "create a swap partition with an explicit UUID",
2964    "\
2965 Create a swap partition on C<device> with UUID C<uuid>.");
2966
2967   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2968    [InitBasicFS, Always, TestOutputStruct (
2969       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2970        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2971        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2972     InitBasicFS, Always, TestOutputStruct (
2973       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2974        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2975    "make block, character or FIFO devices",
2976    "\
2977 This call creates block or character special devices, or
2978 named pipes (FIFOs).
2979
2980 The C<mode> parameter should be the mode, using the standard
2981 constants.  C<devmajor> and C<devminor> are the
2982 device major and minor numbers, only used when creating block
2983 and character special devices.");
2984
2985   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2986    [InitBasicFS, Always, TestOutputStruct (
2987       [["mkfifo"; "0o777"; "/node"];
2988        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2989    "make FIFO (named pipe)",
2990    "\
2991 This call creates a FIFO (named pipe) called C<path> with
2992 mode C<mode>.  It is just a convenient wrapper around
2993 C<guestfs_mknod>.");
2994
2995   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2996    [InitBasicFS, Always, TestOutputStruct (
2997       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2998        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2999    "make block device node",
3000    "\
3001 This call creates a block device node called C<path> with
3002 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3003 It is just a convenient wrapper around C<guestfs_mknod>.");
3004
3005   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3006    [InitBasicFS, Always, TestOutputStruct (
3007       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3008        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3009    "make char device node",
3010    "\
3011 This call creates a char device node called C<path> with
3012 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3013 It is just a convenient wrapper around C<guestfs_mknod>.");
3014
3015   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3016    [], (* XXX umask is one of those stateful things that we should
3017         * reset between each test.
3018         *)
3019    "set file mode creation mask (umask)",
3020    "\
3021 This function sets the mask used for creating new files and
3022 device nodes to C<mask & 0777>.
3023
3024 Typical umask values would be C<022> which creates new files
3025 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3026 C<002> which creates new files with permissions like
3027 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3028
3029 The default umask is C<022>.  This is important because it
3030 means that directories and device nodes will be created with
3031 C<0644> or C<0755> mode even if you specify C<0777>.
3032
3033 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3034
3035 This call returns the previous umask.");
3036
3037   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3038    [],
3039    "read directories entries",
3040    "\
3041 This returns the list of directory entries in directory C<dir>.
3042
3043 All entries in the directory are returned, including C<.> and
3044 C<..>.  The entries are I<not> sorted, but returned in the same
3045 order as the underlying filesystem.
3046
3047 Also this call returns basic file type information about each
3048 file.  The C<ftyp> field will contain one of the following characters:
3049
3050 =over 4
3051
3052 =item 'b'
3053
3054 Block special
3055
3056 =item 'c'
3057
3058 Char special
3059
3060 =item 'd'
3061
3062 Directory
3063
3064 =item 'f'
3065
3066 FIFO (named pipe)
3067
3068 =item 'l'
3069
3070 Symbolic link
3071
3072 =item 'r'
3073
3074 Regular file
3075
3076 =item 's'
3077
3078 Socket
3079
3080 =item 'u'
3081
3082 Unknown file type
3083
3084 =item '?'
3085
3086 The L<readdir(3)> returned a C<d_type> field with an
3087 unexpected value
3088
3089 =back
3090
3091 This function is primarily intended for use by programs.  To
3092 get a simple list of names, use C<guestfs_ls>.  To get a printable
3093 directory for human consumption, use C<guestfs_ll>.");
3094
3095   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3096    [],
3097    "create partitions on a block device",
3098    "\
3099 This is a simplified interface to the C<guestfs_sfdisk>
3100 command, where partition sizes are specified in megabytes
3101 only (rounded to the nearest cylinder) and you don't need
3102 to specify the cyls, heads and sectors parameters which
3103 were rarely if ever used anyway.
3104
3105 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3106 and C<guestfs_part_disk>");
3107
3108   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3109    [],
3110    "determine file type inside a compressed file",
3111    "\
3112 This command runs C<file> after first decompressing C<path>
3113 using C<method>.
3114
3115 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3116
3117 Since 1.0.63, use C<guestfs_file> instead which can now
3118 process compressed files.");
3119
3120   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3121    [],
3122    "list extended attributes of a file or directory",
3123    "\
3124 This call lists the extended attributes of the file or directory
3125 C<path>.
3126
3127 At the system call level, this is a combination of the
3128 L<listxattr(2)> and L<getxattr(2)> calls.
3129
3130 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3131
3132   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3133    [],
3134    "list extended attributes of a file or directory",
3135    "\
3136 This is the same as C<guestfs_getxattrs>, but if C<path>
3137 is a symbolic link, then it returns the extended attributes
3138 of the link itself.");
3139
3140   ("setxattr", (RErr, [String "xattr";
3141                        String "val"; Int "vallen"; (* will be BufferIn *)
3142                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3143    [],
3144    "set extended attribute of a file or directory",
3145    "\
3146 This call sets the extended attribute named C<xattr>
3147 of the file C<path> to the value C<val> (of length C<vallen>).
3148 The value is arbitrary 8 bit data.
3149
3150 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3151
3152   ("lsetxattr", (RErr, [String "xattr";
3153                         String "val"; Int "vallen"; (* will be BufferIn *)
3154                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3155    [],
3156    "set extended attribute of a file or directory",
3157    "\
3158 This is the same as C<guestfs_setxattr>, but if C<path>
3159 is a symbolic link, then it sets an extended attribute
3160 of the link itself.");
3161
3162   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3163    [],
3164    "remove extended attribute of a file or directory",
3165    "\
3166 This call removes the extended attribute named C<xattr>
3167 of the file C<path>.
3168
3169 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3170
3171   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3172    [],
3173    "remove extended attribute of a file or directory",
3174    "\
3175 This is the same as C<guestfs_removexattr>, but if C<path>
3176 is a symbolic link, then it removes an extended attribute
3177 of the link itself.");
3178
3179   ("mountpoints", (RHashtable "mps", []), 147, [],
3180    [],
3181    "show mountpoints",
3182    "\
3183 This call is similar to C<guestfs_mounts>.  That call returns
3184 a list of devices.  This one returns a hash table (map) of
3185 device name to directory where the device is mounted.");
3186
3187   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3188    (* This is a special case: while you would expect a parameter
3189     * of type "Pathname", that doesn't work, because it implies
3190     * NEED_ROOT in the generated calling code in stubs.c, and
3191     * this function cannot use NEED_ROOT.
3192     *)
3193    [],
3194    "create a mountpoint",
3195    "\
3196 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3197 specialized calls that can be used to create extra mountpoints
3198 before mounting the first filesystem.
3199
3200 These calls are I<only> necessary in some very limited circumstances,
3201 mainly the case where you want to mount a mix of unrelated and/or
3202 read-only filesystems together.
3203
3204 For example, live CDs often contain a \"Russian doll\" nest of
3205 filesystems, an ISO outer layer, with a squashfs image inside, with
3206 an ext2/3 image inside that.  You can unpack this as follows
3207 in guestfish:
3208
3209  add-ro Fedora-11-i686-Live.iso
3210  run
3211  mkmountpoint /cd
3212  mkmountpoint /squash
3213  mkmountpoint /ext3
3214  mount /dev/sda /cd
3215  mount-loop /cd/LiveOS/squashfs.img /squash
3216  mount-loop /squash/LiveOS/ext3fs.img /ext3
3217
3218 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3219
3220   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3221    [],
3222    "remove a mountpoint",
3223    "\
3224 This calls removes a mountpoint that was previously created
3225 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3226 for full details.");
3227
3228   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3229    [InitISOFS, Always, TestOutputBuffer (
3230       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3231    "read a file",
3232    "\
3233 This calls returns the contents of the file C<path> as a
3234 buffer.
3235
3236 Unlike C<guestfs_cat>, this function can correctly
3237 handle files that contain embedded ASCII NUL characters.
3238 However unlike C<guestfs_download>, this function is limited
3239 in the total size of file that can be handled.");
3240
3241   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3242    [InitISOFS, Always, TestOutputList (
3243       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3244     InitISOFS, Always, TestOutputList (
3245       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3246    "return lines matching a pattern",
3247    "\
3248 This calls the external C<grep> program and returns the
3249 matching lines.");
3250
3251   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputList (
3253       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3254    "return lines matching a pattern",
3255    "\
3256 This calls the external C<egrep> program and returns the
3257 matching lines.");
3258
3259   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3260    [InitISOFS, Always, TestOutputList (
3261       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3262    "return lines matching a pattern",
3263    "\
3264 This calls the external C<fgrep> program and returns the
3265 matching lines.");
3266
3267   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3268    [InitISOFS, Always, TestOutputList (
3269       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3270    "return lines matching a pattern",
3271    "\
3272 This calls the external C<grep -i> program and returns the
3273 matching lines.");
3274
3275   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3276    [InitISOFS, Always, TestOutputList (
3277       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3278    "return lines matching a pattern",
3279    "\
3280 This calls the external C<egrep -i> program and returns the
3281 matching lines.");
3282
3283   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3284    [InitISOFS, Always, TestOutputList (
3285       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3286    "return lines matching a pattern",
3287    "\
3288 This calls the external C<fgrep -i> program and returns the
3289 matching lines.");
3290
3291   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3292    [InitISOFS, Always, TestOutputList (
3293       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3294    "return lines matching a pattern",
3295    "\
3296 This calls the external C<zgrep> program and returns the
3297 matching lines.");
3298
3299   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3300    [InitISOFS, Always, TestOutputList (
3301       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3302    "return lines matching a pattern",
3303    "\
3304 This calls the external C<zegrep> program and returns the
3305 matching lines.");
3306
3307   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3308    [InitISOFS, Always, TestOutputList (
3309       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3310    "return lines matching a pattern",
3311    "\
3312 This calls the external C<zfgrep> program and returns the
3313 matching lines.");
3314
3315   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3316    [InitISOFS, Always, TestOutputList (
3317       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3318    "return lines matching a pattern",
3319    "\
3320 This calls the external C<zgrep -i> program and returns the
3321 matching lines.");
3322
3323   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3326    "return lines matching a pattern",
3327    "\
3328 This calls the external C<zegrep -i> program and returns the
3329 matching lines.");
3330
3331   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3332    [InitISOFS, Always, TestOutputList (
3333       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3334    "return lines matching a pattern",
3335    "\
3336 This calls the external C<zfgrep -i> program and returns the
3337 matching lines.");
3338
3339   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3340    [InitISOFS, Always, TestOutput (
3341       [["realpath"; "/../directory"]], "/directory")],
3342    "canonicalized absolute pathname",
3343    "\
3344 Return the canonicalized absolute pathname of C<path>.  The
3345 returned path has no C<.>, C<..> or symbolic link path elements.");
3346
3347   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3348    [InitBasicFS, Always, TestOutputStruct (
3349       [["touch"; "/a"];
3350        ["ln"; "/a"; "/b"];
3351        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3352    "create a hard link",
3353    "\
3354 This command creates a hard link using the C<ln> command.");
3355
3356   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3357    [InitBasicFS, Always, TestOutputStruct (
3358       [["touch"; "/a"];
3359        ["touch"; "/b"];
3360        ["ln_f"; "/a"; "/b"];
3361        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3362    "create a hard link",
3363    "\
3364 This command creates a hard link using the C<ln -f> command.
3365 The C<-f> option removes the link (C<linkname>) if it exists already.");
3366
3367   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3368    [InitBasicFS, Always, TestOutputStruct (
3369       [["touch"; "/a"];
3370        ["ln_s"; "a"; "/b"];
3371        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3372    "create a symbolic link",
3373    "\
3374 This command creates a symbolic link using the C<ln -s> command.");
3375
3376   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3377    [InitBasicFS, Always, TestOutput (
3378       [["mkdir_p"; "/a/b"];
3379        ["touch"; "/a/b/c"];
3380        ["ln_sf"; "../d"; "/a/b/c"];
3381        ["readlink"; "/a/b/c"]], "../d")],
3382    "create a symbolic link",
3383    "\
3384 This command creates a symbolic link using the C<ln -sf> command,
3385 The C<-f> option removes the link (C<linkname>) if it exists already.");
3386
3387   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3388    [] (* XXX tested above *),
3389    "read the target of a symbolic link",
3390    "\
3391 This command reads the target of a symbolic link.");
3392
3393   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3394    [InitBasicFS, Always, TestOutputStruct (
3395       [["fallocate"; "/a"; "1000000"];
3396        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3397    "preallocate a file in the guest filesystem",
3398    "\
3399 This command preallocates a file (containing zero bytes) named
3400 C<path> of size C<len> bytes.  If the file exists already, it
3401 is overwritten.
3402
3403 Do not confuse this with the guestfish-specific
3404 C<alloc> command which allocates a file in the host and
3405 attaches it as a device.");
3406
3407   ("swapon_device", (RErr, [Device "device"]), 170, [],
3408    [InitPartition, Always, TestRun (
3409       [["mkswap"; "/dev/sda1"];
3410        ["swapon_device"; "/dev/sda1"];
3411        ["swapoff_device"; "/dev/sda1"]])],
3412    "enable swap on device",
3413    "\
3414 This command enables the libguestfs appliance to use the
3415 swap device or partition named C<device>.  The increased
3416 memory is made available for all commands, for example
3417 those run using C<guestfs_command> or C<guestfs_sh>.
3418
3419 Note that you should not swap to existing guest swap
3420 partitions unless you know what you are doing.  They may
3421 contain hibernation information, or other information that
3422 the guest doesn't want you to trash.  You also risk leaking
3423 information about the host to the guest this way.  Instead,
3424 attach a new host device to the guest and swap on that.");
3425
3426   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3427    [], (* XXX tested by swapon_device *)
3428    "disable swap on device",
3429    "\
3430 This command disables the libguestfs appliance swap
3431 device or partition named C<device>.
3432 See C<guestfs_swapon_device>.");
3433
3434   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3435    [InitBasicFS, Always, TestRun (
3436       [["fallocate"; "/swap"; "8388608"];
3437        ["mkswap_file"; "/swap"];
3438        ["swapon_file"; "/swap"];
3439        ["swapoff_file"; "/swap"]])],
3440    "enable swap on file",
3441    "\
3442 This command enables swap to a file.
3443 See C<guestfs_swapon_device> for other notes.");
3444
3445   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3446    [], (* XXX tested by swapon_file *)
3447    "disable swap on file",
3448    "\
3449 This command disables the libguestfs appliance swap on file.");
3450
3451   ("swapon_label", (RErr, [String "label"]), 174, [],
3452    [InitEmpty, Always, TestRun (
3453       [["part_disk"; "/dev/sdb"; "mbr"];
3454        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3455        ["swapon_label"; "swapit"];
3456        ["swapoff_label"; "swapit"];
3457        ["zero"; "/dev/sdb"];
3458        ["blockdev_rereadpt"; "/dev/sdb"]])],
3459    "enable swap on labeled swap partition",
3460    "\
3461 This command enables swap to a labeled swap partition.
3462 See C<guestfs_swapon_device> for other notes.");
3463
3464   ("swapoff_label", (RErr, [String "label"]), 175, [],
3465    [], (* XXX tested by swapon_label *)
3466    "disable swap on labeled swap partition",
3467    "\
3468 This command disables the libguestfs appliance swap on
3469 labeled swap partition.");
3470
3471   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3472    (let uuid = uuidgen () in
3473     [InitEmpty, Always, TestRun (
3474        [["mkswap_U"; uuid; "/dev/sdb"];
3475         ["swapon_uuid"; uuid];
3476         ["swapoff_uuid"; uuid]])]),
3477    "enable swap on swap partition by UUID",
3478    "\
3479 This command enables swap to a swap partition with the given UUID.
3480 See C<guestfs_swapon_device> for other notes.");
3481
3482   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3483    [], (* XXX tested by swapon_uuid *)
3484    "disable swap on swap partition by UUID",
3485    "\
3486 This command disables the libguestfs appliance swap partition
3487 with the given UUID.");
3488
3489   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3490    [InitBasicFS, Always, TestRun (
3491       [["fallocate"; "/swap"; "8388608"];
3492        ["mkswap_file"; "/swap"]])],
3493    "create a swap file",
3494    "\
3495 Create a swap file.
3496
3497 This command just writes a swap file signature to an existing
3498 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3499
3500   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3501    [InitISOFS, Always, TestRun (
3502       [["inotify_init"; "0"]])],
3503    "create an inotify handle",
3504    "\
3505 This command creates a new inotify handle.
3506 The inotify subsystem can be used to notify events which happen to
3507 objects in the guest filesystem.
3508
3509 C<maxevents> is the maximum number of events which will be
3510 queued up between calls to C<guestfs_inotify_read> or
3511 C<guestfs_inotify_files>.
3512 If this is passed as C<0>, then the kernel (or previously set)
3513 default is used.  For Linux 2.6.29 the default was 16384 events.
3514 Beyond this limit, the kernel throws away events, but records
3515 the fact that it threw them away by setting a flag
3516 C<IN_Q_OVERFLOW> in the returned structure list (see
3517 C<guestfs_inotify_read>).
3518
3519 Before any events are generated, you have to add some
3520 watches to the internal watch list.  See:
3521 C<guestfs_inotify_add_watch>,
3522 C<guestfs_inotify_rm_watch> and
3523 C<guestfs_inotify_watch_all>.
3524
3525 Queued up events should be read periodically by calling
3526 C<guestfs_inotify_read>
3527 (or C<guestfs_inotify_files> which is just a helpful
3528 wrapper around C<guestfs_inotify_read>).  If you don't
3529 read the events out often enough then you risk the internal
3530 queue overflowing.
3531
3532 The handle should be closed after use by calling
3533 C<guestfs_inotify_close>.  This also removes any
3534 watches automatically.
3535
3536 See also L<inotify(7)> for an overview of the inotify interface
3537 as exposed by the Linux kernel, which is roughly what we expose
3538 via libguestfs.  Note that there is one global inotify handle
3539 per libguestfs instance.");
3540
3541   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3542    [InitBasicFS, Always, TestOutputList (
3543       [["inotify_init"; "0"];
3544        ["inotify_add_watch"; "/"; "1073741823"];
3545        ["touch"; "/a"];
3546        ["touch"; "/b"];
3547        ["inotify_files"]], ["a"; "b"])],
3548    "add an inotify watch",
3549    "\
3550 Watch C<path> for the events listed in C<mask>.
3551
3552 Note that if C<path> is a directory then events within that
3553 directory are watched, but this does I<not> happen recursively
3554 (in subdirectories).
3555
3556 Note for non-C or non-Linux callers: the inotify events are
3557 defined by the Linux kernel ABI and are listed in
3558 C</usr/include/sys/inotify.h>.");
3559
3560   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3561    [],
3562    "remove an inotify watch",
3563    "\
3564 Remove a previously defined inotify watch.
3565 See C<guestfs_inotify_add_watch>.");
3566
3567   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3568    [],
3569    "return list of inotify events",
3570    "\
3571 Return the complete queue of events that have happened
3572 since the previous read call.
3573
3574 If no events have happened, this returns an empty list.
3575
3576 I<Note>: In order to make sure that all events have been
3577 read, you must call this function repeatedly until it
3578 returns an empty list.  The reason is that the call will
3579 read events up to the maximum appliance-to-host message
3580 size and leave remaining events in the queue.");
3581
3582   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3583    [],
3584    "return list of watched files that had events",
3585    "\
3586 This function is a helpful wrapper around C<guestfs_inotify_read>
3587 which just returns a list of pathnames of objects that were
3588 touched.  The returned pathnames are sorted and deduplicated.");
3589
3590   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3591    [],
3592    "close the inotify handle",
3593    "\
3594 This closes the inotify handle which was previously
3595 opened by inotify_init.  It removes all watches, throws
3596 away any pending events, and deallocates all resources.");
3597
3598   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3599    [],
3600    "set SELinux security context",
3601    "\
3602 This sets the SELinux security context of the daemon
3603 to the string C<context>.
3604
3605 See the documentation about SELINUX in L<guestfs(3)>.");
3606
3607   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3608    [],
3609    "get SELinux security context",
3610    "\
3611 This gets the SELinux security context of the daemon.
3612
3613 See the documentation about SELINUX in L<guestfs(3)>,
3614 and C<guestfs_setcon>");
3615
3616   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3617    [InitEmpty, Always, TestOutput (
3618       [["part_disk"; "/dev/sda"; "mbr"];
3619        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3620        ["mount_options"; ""; "/dev/sda1"; "/"];
3621        ["write_file"; "/new"; "new file contents"; "0"];
3622        ["cat"; "/new"]], "new file contents")],
3623    "make a filesystem with block size",
3624    "\
3625 This call is similar to C<guestfs_mkfs>, but it allows you to
3626 control the block size of the resulting filesystem.  Supported
3627 block sizes depend on the filesystem type, but typically they
3628 are C<1024>, C<2048> or C<4096> only.");
3629
3630   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3631    [InitEmpty, Always, TestOutput (
3632       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3633        ["mke2journal"; "4096"; "/dev/sda1"];
3634        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3635        ["mount_options"; ""; "/dev/sda2"; "/"];
3636        ["write_file"; "/new"; "new file contents"; "0"];
3637        ["cat"; "/new"]], "new file contents")],
3638    "make ext2/3/4 external journal",
3639    "\
3640 This creates an ext2 external journal on C<device>.  It is equivalent
3641 to the command:
3642
3643  mke2fs -O journal_dev -b blocksize device");
3644
3645   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3646    [InitEmpty, Always, TestOutput (
3647       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3648        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3649        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3650        ["mount_options"; ""; "/dev/sda2"; "/"];
3651        ["write_file"; "/new"; "new file contents"; "0"];
3652        ["cat"; "/new"]], "new file contents")],
3653    "make ext2/3/4 external journal with label",
3654    "\
3655 This creates an ext2 external journal on C<device> with label C<label>.");
3656
3657   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3658    (let uuid = uuidgen () in
3659     [InitEmpty, Always, TestOutput (
3660        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3661         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3662         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3663         ["mount_options"; ""; "/dev/sda2"; "/"];
3664         ["write_file"; "/new"; "new file contents"; "0"];
3665         ["cat"; "/new"]], "new file contents")]),
3666    "make ext2/3/4 external journal with UUID",
3667    "\
3668 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3669
3670   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3671    [],
3672    "make ext2/3/4 filesystem with external journal",
3673    "\
3674 This creates an ext2/3/4 filesystem on C<device> with
3675 an external journal on C<journal>.  It is equivalent
3676 to the command:
3677
3678  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3679
3680 See also C<guestfs_mke2journal>.");
3681
3682   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3683    [],
3684    "make ext2/3/4 filesystem with external journal",
3685    "\
3686 This creates an ext2/3/4 filesystem on C<device> with
3687 an external journal on the journal labeled C<label>.
3688
3689 See also C<guestfs_mke2journal_L>.");
3690
3691   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3692    [],
3693    "make ext2/3/4 filesystem with external journal",
3694    "\
3695 This creates an ext2/3/4 filesystem on C<device> with
3696 an external journal on the journal with UUID C<uuid>.
3697
3698 See also C<guestfs_mke2journal_U>.");
3699
3700   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3701    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3702    "load a kernel module",
3703    "\
3704 This loads a kernel module in the appliance.
3705
3706 The kernel module must have been whitelisted when libguestfs
3707 was built (see C<appliance/kmod.whitelist.in> in the source).");
3708
3709   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3710    [InitNone, Always, TestOutput (
3711       [["echo_daemon"; "This is a test"]], "This is a test"
3712     )],
3713    "echo arguments back to the client",
3714    "\
3715 This command concatenate the list of C<words> passed with single spaces between
3716 them and returns the resulting string.
3717
3718 You can use this command to test the connection through to the daemon.
3719
3720 See also C<guestfs_ping_daemon>.");
3721
3722   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3723    [], (* There is a regression test for this. *)
3724    "find all files and directories, returning NUL-separated list",
3725    "\
3726 This command lists out all files and directories, recursively,
3727 starting at C<directory>, placing the resulting list in the
3728 external file called C<files>.
3729
3730 This command works the same way as C<guestfs_find> with the
3731 following exceptions:
3732
3733 =over 4
3734
3735 =item *
3736
3737 The resulting list is written to an external file.
3738
3739 =item *
3740
3741 Items (filenames) in the result are separated
3742 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3743
3744 =item *
3745
3746 This command is not limited in the number of names that it
3747 can return.
3748
3749 =item *
3750
3751 The result list is not sorted.
3752
3753 =back");
3754
3755   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3756    [InitISOFS, Always, TestOutput (
3757       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3758     InitISOFS, Always, TestOutput (
3759       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3760     InitISOFS, Always, TestOutput (
3761       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3762     InitISOFS, Always, TestLastFail (
3763       [["case_sensitive_path"; "/Known-1/"]]);
3764     InitBasicFS, Always, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestOutput (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3774     InitBasicFS, Always, TestLastFail (
3775       [["mkdir"; "/a"];
3776        ["mkdir"; "/a/bbb"];
3777        ["touch"; "/a/bbb/c"];
3778        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3779    "return true path on case-insensitive filesystem",
3780    "\
3781 This can be used to resolve case insensitive paths on
3782 a filesystem which is case sensitive.  The use case is
3783 to resolve paths which you have read from Windows configuration
3784 files or the Windows Registry, to the true path.
3785
3786 The command handles a peculiarity of the Linux ntfs-3g
3787 filesystem driver (and probably others), which is that although
3788 the underlying filesystem is case-insensitive, the driver
3789 exports the filesystem to Linux as case-sensitive.
3790
3791 One consequence of this is that special directories such
3792 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3793 (or other things) depending on the precise details of how
3794 they were created.  In Windows itself this would not be
3795 a problem.
3796
3797 Bug or feature?  You decide:
3798 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3799
3800 This function resolves the true case of each element in the
3801 path and returns the case-sensitive path.
3802
3803 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3804 might return C<\"/WINDOWS/system32\"> (the exact return value
3805 would depend on details of how the directories were originally
3806 created under Windows).
3807
3808 I<Note>:
3809 This function does not handle drive names, backslashes etc.
3810
3811 See also C<guestfs_realpath>.");
3812
3813   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3814    [InitBasicFS, Always, TestOutput (
3815       [["vfs_type"; "/dev/sda1"]], "ext2")],
3816    "get the Linux VFS type corresponding to a mounted device",
3817    "\
3818 This command gets the block device type corresponding to
3819 a mounted device called C<device>.
3820
3821 Usually the result is the name of the Linux VFS module that
3822 is used to mount this device (probably determined automatically
3823 if you used the C<guestfs_mount> call).");
3824
3825   ("truncate", (RErr, [Pathname "path"]), 199, [],
3826    [InitBasicFS, Always, TestOutputStruct (
3827       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3828        ["truncate"; "/test"];
3829        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3830    "truncate a file to zero size",
3831    "\
3832 This command truncates C<path> to a zero-length file.  The
3833 file must exist already.");
3834
3835   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3836    [InitBasicFS, Always, TestOutputStruct (
3837       [["touch"; "/test"];
3838        ["truncate_size"; "/test"; "1000"];
3839        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3840    "truncate a file to a particular size",
3841    "\
3842 This command truncates C<path> to size C<size> bytes.  The file
3843 must exist already.  If the file is smaller than C<size> then
3844 the file is extended to the required size with null bytes.");
3845
3846   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3847    [InitBasicFS, Always, TestOutputStruct (
3848       [["touch"; "/test"];
3849        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3850        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3851    "set timestamp of a file with nanosecond precision",
3852    "\
3853 This command sets the timestamps of a file with nanosecond
3854 precision.
3855
3856 C<atsecs, atnsecs> are the last access time (atime) in secs and
3857 nanoseconds from the epoch.
3858
3859 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3860 secs and nanoseconds from the epoch.
3861
3862 If the C<*nsecs> field contains the special value C<-1> then
3863 the corresponding timestamp is set to the current time.  (The
3864 C<*secs> field is ignored in this case).
3865
3866 If the C<*nsecs> field contains the special value C<-2> then
3867 the corresponding timestamp is left unchanged.  (The
3868 C<*secs> field is ignored in this case).");
3869
3870   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3871    [InitBasicFS, Always, TestOutputStruct (
3872       [["mkdir_mode"; "/test"; "0o111"];
3873        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3874    "create a directory with a particular mode",
3875    "\
3876 This command creates a directory, setting the initial permissions
3877 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3878
3879   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3880    [], (* XXX *)
3881    "change file owner and group",
3882    "\
3883 Change the file owner to C<owner> and group to C<group>.
3884 This is like C<guestfs_chown> but if C<path> is a symlink then
3885 the link itself is changed, not the target.
3886
3887 Only numeric uid and gid are supported.  If you want to use
3888 names, you will need to locate and parse the password file
3889 yourself (Augeas support makes this relatively easy).");
3890
3891   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3892    [], (* XXX *)
3893    "lstat on multiple files",
3894    "\
3895 This call allows you to perform the C<guestfs_lstat> operation
3896 on multiple files, where all files are in the directory C<path>.
3897 C<names> is the list of files from this directory.
3898
3899 On return you get a list of stat structs, with a one-to-one
3900 correspondence to the C<names> list.  If any name did not exist
3901 or could not be lstat'd, then the C<ino> field of that structure
3902 is set to C<-1>.
3903
3904 This call is intended for programs that want to efficiently
3905 list a directory contents without making many round-trips.
3906 See also C<guestfs_lxattrlist> for a similarly efficient call
3907 for getting extended attributes.  Very long directory listings
3908 might cause the protocol message size to be exceeded, causing
3909 this call to fail.  The caller must split up such requests
3910 into smaller groups of names.");
3911
3912   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3913    [], (* XXX *)
3914    "lgetxattr on multiple files",
3915    "\
3916 This call allows you to get the extended attributes
3917 of multiple files, where all files are in the directory C<path>.
3918 C<names> is the list of files from this directory.
3919
3920 On return you get a flat list of xattr structs which must be
3921 interpreted sequentially.  The first xattr struct always has a zero-length
3922 C<attrname>.  C<attrval> in this struct is zero-length
3923 to indicate there was an error doing C<lgetxattr> for this
3924 file, I<or> is a C string which is a decimal number
3925 (the number of following attributes for this file, which could
3926 be C<\"0\">).  Then after the first xattr struct are the
3927 zero or more attributes for the first named file.
3928 This repeats for the second and subsequent files.
3929
3930 This call is intended for programs that want to efficiently
3931 list a directory contents without making many round-trips.
3932 See also C<guestfs_lstatlist> for a similarly efficient call
3933 for getting standard stats.  Very long directory listings
3934 might cause the protocol message size to be exceeded, causing
3935 this call to fail.  The caller must split up such requests
3936 into smaller groups of names.");
3937
3938   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3939    [], (* XXX *)
3940    "readlink on multiple files",
3941    "\
3942 This call allows you to do a C<readlink> operation
3943 on multiple files, where all files are in the directory C<path>.
3944 C<names> is the list of files from this directory.
3945
3946 On return you get a list of strings, with a one-to-one
3947 correspondence to the C<names> list.  Each string is the
3948 value of the symbol link.
3949
3950 If the C<readlink(2)> operation fails on any name, then
3951 the corresponding result string is the empty string C<\"\">.
3952 However the whole operation is completed even if there
3953 were C<readlink(2)> errors, and so you can call this
3954 function with names where you don't know if they are
3955 symbolic links already (albeit slightly less efficient).
3956
3957 This call is intended for programs that want to efficiently
3958 list a directory contents without making many round-trips.
3959 Very long directory listings might cause the protocol
3960 message size to be exceeded, causing
3961 this call to fail.  The caller must split up such requests
3962 into smaller groups of names.");
3963
3964   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3965    [InitISOFS, Always, TestOutputBuffer (
3966       [["pread"; "/known-4"; "1"; "3"]], "\n");
3967     InitISOFS, Always, TestOutputBuffer (
3968       [["pread"; "/empty"; "0"; "100"]], "")],
3969    "read part of a file",
3970    "\
3971 This command lets you read part of a file.  It reads C<count>
3972 bytes of the file, starting at C<offset>, from file C<path>.
3973
3974 This may read fewer bytes than requested.  For further details
3975 see the L<pread(2)> system call.");
3976
3977   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3978    [InitEmpty, Always, TestRun (
3979       [["part_init"; "/dev/sda"; "gpt"]])],
3980    "create an empty partition table",
3981    "\
3982 This creates an empty partition table on C<device> of one of the
3983 partition types listed below.  Usually C<parttype> should be
3984 either C<msdos> or C<gpt> (for large disks).
3985
3986 Initially there are no partitions.  Following this, you should
3987 call C<guestfs_part_add> for each partition required.
3988
3989 Possible values for C<parttype> are:
3990
3991 =over 4
3992
3993 =item B<efi> | B<gpt>
3994
3995 Intel EFI / GPT partition table.
3996
3997 This is recommended for >= 2 TB partitions that will be accessed
3998 from Linux and Intel-based Mac OS X.  It also has limited backwards
3999 compatibility with the C<mbr> format.
4000
4001 =item B<mbr> | B<msdos>
4002
4003 The standard PC \"Master Boot Record\" (MBR) format used
4004 by MS-DOS and Windows.  This partition type will B<only> work
4005 for device sizes up to 2 TB.  For large disks we recommend
4006 using C<gpt>.
4007
4008 =back
4009
4010 Other partition table types that may work but are not
4011 supported include:
4012
4013 =over 4
4014
4015 =item B<aix>
4016
4017 AIX disk labels.
4018
4019 =item B<amiga> | B<rdb>
4020
4021 Amiga \"Rigid Disk Block\" format.
4022
4023 =item B<bsd>
4024
4025 BSD disk labels.
4026
4027 =item B<dasd>
4028
4029 DASD, used on IBM mainframes.
4030
4031 =item B<dvh>
4032
4033 MIPS/SGI volumes.
4034
4035 =item B<mac>
4036
4037 Old Mac partition format.  Modern Macs use C<gpt>.
4038
4039 =item B<pc98>
4040
4041 NEC PC-98 format, common in Japan apparently.
4042
4043 =item B<sun>
4044
4045 Sun disk labels.
4046
4047 =back");
4048
4049   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4050    [InitEmpty, Always, TestRun (
4051       [["part_init"; "/dev/sda"; "mbr"];
4052        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4053     InitEmpty, Always, TestRun (
4054       [["part_init"; "/dev/sda"; "gpt"];
4055        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4056        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4057     InitEmpty, Always, TestRun (
4058       [["part_init"; "/dev/sda"; "mbr"];
4059        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4060        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4061        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4062        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4063    "add a partition to the device",
4064    "\
4065 This command adds a partition to C<device>.  If there is no partition
4066 table on the device, call C<guestfs_part_init> first.
4067
4068 The C<prlogex> parameter is the type of partition.  Normally you
4069 should pass C<p> or C<primary> here, but MBR partition tables also
4070 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4071 types.
4072
4073 C<startsect> and C<endsect> are the start and end of the partition
4074 in I<sectors>.  C<endsect> may be negative, which means it counts
4075 backwards from the end of the disk (C<-1> is the last sector).
4076
4077 Creating a partition which covers the whole disk is not so easy.
4078 Use C<guestfs_part_disk> to do that.");
4079
4080   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4081    [InitEmpty, Always, TestRun (
4082       [["part_disk"; "/dev/sda"; "mbr"]]);
4083     InitEmpty, Always, TestRun (
4084       [["part_disk"; "/dev/sda"; "gpt"]])],
4085    "partition whole disk with a single primary partition",
4086    "\
4087 This command is simply a combination of C<guestfs_part_init>
4088 followed by C<guestfs_part_add> to create a single primary partition
4089 covering the whole disk.
4090
4091 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4092 but other possible values are described in C<guestfs_part_init>.");
4093
4094   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4095    [InitEmpty, Always, TestRun (
4096       [["part_disk"; "/dev/sda"; "mbr"];
4097        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4098    "make a partition bootable",
4099    "\
4100 This sets the bootable flag on partition numbered C<partnum> on
4101 device C<device>.  Note that partitions are numbered from 1.
4102
4103 The bootable flag is used by some operating systems (notably
4104 Windows) to determine which partition to boot from.  It is by
4105 no means universally recognized.");
4106
4107   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4108    [InitEmpty, Always, TestRun (
4109       [["part_disk"; "/dev/sda"; "gpt"];
4110        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4111    "set partition name",
4112    "\
4113 This sets the partition name on partition numbered C<partnum> on
4114 device C<device>.  Note that partitions are numbered from 1.
4115
4116 The partition name can only be set on certain types of partition
4117 table.  This works on C<gpt> but not on C<mbr> partitions.");
4118
4119   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4120    [], (* XXX Add a regression test for this. *)
4121    "list partitions on a device",
4122    "\
4123 This command parses the partition table on C<device> and
4124 returns the list of partitions found.
4125
4126 The fields in the returned structure are:
4127
4128 =over 4
4129
4130 =item B<part_num>
4131
4132 Partition number, counting from 1.
4133
4134 =item B<part_start>
4135
4136 Start of the partition I<in bytes>.  To get sectors you have to
4137 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4138
4139 =item B<part_end>
4140
4141 End of the partition in bytes.
4142
4143 =item B<part_size>
4144
4145 Size of the partition in bytes.
4146
4147 =back");
4148
4149   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4150    [InitEmpty, Always, TestOutput (
4151       [["part_disk"; "/dev/sda"; "gpt"];
4152        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4153    "get the partition table type",
4154    "\
4155 This command examines the partition table on C<device> and
4156 returns the partition table type (format) being used.
4157
4158 Common return values include: C<msdos> (a DOS/Windows style MBR
4159 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4160 values are possible, although unusual.  See C<guestfs_part_init>
4161 for a full list.");
4162
4163   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4164    [InitBasicFS, Always, TestOutputBuffer (
4165       [["fill"; "0x63"; "10"; "/test"];
4166        ["read_file"; "/test"]], "cccccccccc")],
4167    "fill a file with octets",
4168    "\
4169 This command creates a new file called C<path>.  The initial
4170 content of the file is C<len> octets of C<c>, where C<c>
4171 must be a number in the range C<[0..255]>.
4172
4173 To fill a file with zero bytes (sparsely), it is
4174 much more efficient to use C<guestfs_truncate_size>.");
4175
4176   ("available", (RErr, [StringList "groups"]), 216, [],
4177    [InitNone, Always, TestRun [["available"; ""]]],
4178    "test availability of some parts of the API",
4179    "\
4180 This command is used to check the availability of some
4181 groups of functionality in the appliance, which not all builds of
4182 the libguestfs appliance will be able to provide.
4183
4184 The libguestfs groups, and the functions that those
4185 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4186
4187 The argument C<groups> is a list of group names, eg:
4188 C<[\"inotify\", \"augeas\"]> would check for the availability of
4189 the Linux inotify functions and Augeas (configuration file
4190 editing) functions.
4191
4192 The command returns no error if I<all> requested groups are available.
4193
4194 It fails with an error if one or more of the requested
4195 groups is unavailable in the appliance.
4196
4197 If an unknown group name is included in the
4198 list of groups then an error is always returned.
4199
4200 I<Notes:>
4201
4202 =over 4
4203
4204 =item *
4205
4206 You must call C<guestfs_launch> before calling this function.
4207
4208 The reason is because we don't know what groups are
4209 supported by the appliance/daemon until it is running and can
4210 be queried.
4211
4212 =item *
4213
4214 If a group of functions is available, this does not necessarily
4215 mean that they will work.  You still have to check for errors
4216 when calling individual API functions even if they are
4217 available.
4218
4219 =item *
4220
4221 It is usually the job of distro packagers to build
4222 complete functionality into the libguestfs appliance.
4223 Upstream libguestfs, if built from source with all
4224 requirements satisfied, will support everything.
4225
4226 =item *
4227
4228 This call was added in version C<1.0.80>.  In previous
4229 versions of libguestfs all you could do would be to speculatively
4230 execute a command to find out if the daemon implemented it.
4231 See also C<guestfs_version>.
4232
4233 =back");
4234
4235   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4236    [InitBasicFS, Always, TestOutputBuffer (
4237       [["write_file"; "/src"; "hello, world"; "0"];
4238        ["dd"; "/src"; "/dest"];
4239        ["read_file"; "/dest"]], "hello, world")],
4240    "copy from source to destination using dd",
4241    "\
4242 This command copies from one source device or file C<src>
4243 to another destination device or file C<dest>.  Normally you
4244 would use this to copy to or from a device or partition, for
4245 example to duplicate a filesystem.
4246
4247 If the destination is a device, it must be as large or larger
4248 than the source file or device, otherwise the copy will fail.
4249 This command cannot do partial copies (see C<guestfs_copy_size>).");
4250
4251   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4252    [InitBasicFS, Always, TestOutputInt (
4253       [["write_file"; "/file"; "hello, world"; "0"];
4254        ["filesize"; "/file"]], 12)],
4255    "return the size of the file in bytes",
4256    "\
4257 This command returns the size of C<file> in bytes.
4258
4259 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4260 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4261 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4262
4263   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4264    [InitBasicFSonLVM, Always, TestOutputList (
4265       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4266        ["lvs"]], ["/dev/VG/LV2"])],
4267    "rename an LVM logical volume",
4268    "\
4269 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4270
4271   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4272    [InitBasicFSonLVM, Always, TestOutputList (
4273       [["umount"; "/"];
4274        ["vg_activate"; "false"; "VG"];
4275        ["vgrename"; "VG"; "VG2"];
4276        ["vg_activate"; "true"; "VG2"];
4277        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4278        ["vgs"]], ["VG2"])],
4279    "rename an LVM volume group",
4280    "\
4281 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4282
4283   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4284    [InitISOFS, Always, TestOutputBuffer (
4285       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4286    "list the contents of a single file in an initrd",
4287    "\
4288 This command unpacks the file C<filename> from the initrd file
4289 called C<initrdpath>.  The filename must be given I<without> the
4290 initial C</> character.
4291
4292 For example, in guestfish you could use the following command
4293 to examine the boot script (usually called C</init>)
4294 contained in a Linux initrd or initramfs image:
4295
4296  initrd-cat /boot/initrd-<version>.img init
4297
4298 See also C<guestfs_initrd_list>.");
4299
4300   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4301    [],
4302    "get the UUID of a physical volume",
4303    "\
4304 This command returns the UUID of the LVM PV C<device>.");
4305
4306   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4307    [],
4308    "get the UUID of a volume group",
4309    "\
4310 This command returns the UUID of the LVM VG named C<vgname>.");
4311
4312   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4313    [],
4314    "get the UUID of a logical volume",
4315    "\
4316 This command returns the UUID of the LVM LV C<device>.");
4317
4318   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4319    [],
4320    "get the PV UUIDs containing the volume group",
4321    "\
4322 Given a VG called C<vgname>, this returns the UUIDs of all
4323 the physical volumes that this volume group resides on.
4324
4325 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4326 calls to associate physical volumes and volume groups.
4327
4328 See also C<guestfs_vglvuuids>.");
4329
4330   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4331    [],
4332    "get the LV UUIDs of all LVs in the volume group",
4333    "\
4334 Given a VG called C<vgname>, this returns the UUIDs of all
4335 the logical volumes created in this volume group.
4336
4337 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4338 calls to associate logical volumes and volume groups.
4339
4340 See also C<guestfs_vgpvuuids>.");
4341
4342   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4343    [InitBasicFS, Always, TestOutputBuffer (
4344       [["write_file"; "/src"; "hello, world"; "0"];
4345        ["copy_size"; "/src"; "/dest"; "5"];
4346        ["read_file"; "/dest"]], "hello")],
4347    "copy size bytes from source to destination using dd",
4348    "\
4349 This command copies exactly C<size> bytes from one source device
4350 or file C<src> to another destination device or file C<dest>.
4351
4352 Note this will fail if the source is too short or if the destination
4353 is not large enough.");
4354
4355   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4356    [InitBasicFSonLVM, Always, TestRun (
4357       [["zero_device"; "/dev/VG/LV"]])],
4358    "write zeroes to an entire device",
4359    "\
4360 This command writes zeroes over the entire C<device>.  Compare
4361 with C<guestfs_zero> which just zeroes the first few blocks of
4362 a device.");
4363
4364   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4365    [InitBasicFS, Always, TestOutput (
4366       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4367        ["cat"; "/hello"]], "hello\n")],
4368    "unpack compressed tarball to directory",
4369    "\
4370 This command uploads and unpacks local file C<tarball> (an
4371 I<xz compressed> tar file) into C<directory>.");
4372
4373   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4374    [],
4375    "pack directory into compressed tarball",
4376    "\
4377 This command packs the contents of C<directory> and downloads
4378 it to local file C<tarball> (as an xz compressed tar archive).");
4379
4380   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4381    [],
4382    "resize an NTFS filesystem",
4383    "\
4384 This command resizes an NTFS filesystem, expanding or
4385 shrinking it to the size of the underlying device.
4386 See also L<ntfsresize(8)>.");
4387
4388   ("vgscan", (RErr, []), 232, [],
4389    [InitEmpty, Always, TestRun (
4390       [["vgscan"]])],
4391    "rescan for LVM physical volumes, volume groups and logical volumes",
4392    "\
4393 This rescans all block devices and rebuilds the list of LVM
4394 physical volumes, volume groups and logical volumes.");
4395
4396   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4397    [InitEmpty, Always, TestRun (
4398       [["part_init"; "/dev/sda"; "mbr"];
4399        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4400        ["part_del"; "/dev/sda"; "1"]])],
4401    "delete a partition",
4402    "\
4403 This command deletes the partition numbered C<partnum> on C<device>.
4404
4405 Note that in the case of MBR partitioning, deleting an
4406 extended partition also deletes any logical partitions
4407 it contains.");
4408
4409   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4410    [InitEmpty, Always, TestOutputTrue (
4411       [["part_init"; "/dev/sda"; "mbr"];
4412        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4413        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4414        ["part_get_bootable"; "/dev/sda"; "1"]])],
4415    "return true if a partition is bootable",
4416    "\
4417 This command returns true if the partition C<partnum> on
4418 C<device> has the bootable flag set.
4419
4420 See also C<guestfs_part_set_bootable>.");
4421
4422   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4423    [InitEmpty, Always, TestOutputInt (
4424       [["part_init"; "/dev/sda"; "mbr"];
4425        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4426        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4427        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4428    "get the MBR type byte (ID byte) from a partition",
4429    "\
4430 Returns the MBR type byte (also known as the ID byte) from
4431 the numbered partition C<partnum>.
4432
4433 Note that only MBR (old DOS-style) partitions have type bytes.
4434 You will get undefined results for other partition table
4435 types (see C<guestfs_part_get_parttype>).");
4436
4437   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4438    [], (* tested by part_get_mbr_id *)
4439    "set the MBR type byte (ID byte) of a partition",
4440    "\
4441 Sets the MBR type byte (also known as the ID byte) of
4442 the numbered partition C<partnum> to C<idbyte>.  Note
4443 that the type bytes quoted in most documentation are
4444 in fact hexadecimal numbers, but usually documented
4445 without any leading \"0x\" which might be confusing.
4446
4447 Note that only MBR (old DOS-style) partitions have type bytes.
4448 You will get undefined results for other partition table
4449 types (see C<guestfs_part_get_parttype>).");
4450
4451   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4452    [InitISOFS, Always, TestOutput (
4453       [["checksum_device"; "md5"; "/dev/sdd"]],
4454       (Digest.to_hex (Digest.file "images/test.iso")))],
4455    "compute MD5, SHAx or CRC checksum of the contents of a device",
4456    "\
4457 This call computes the MD5, SHAx or CRC checksum of the
4458 contents of the device named C<device>.  For the types of
4459 checksums supported see the C<guestfs_checksum> command.");
4460
4461   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4462    [InitNone, Always, TestRun (
4463       [["part_disk"; "/dev/sda"; "mbr"];
4464        ["pvcreate"; "/dev/sda1"];
4465        ["vgcreate"; "VG"; "/dev/sda1"];
4466        ["lvcreate"; "LV"; "VG"; "10"];
4467        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4468    "expand an LV to fill free space",
4469    "\
4470 This expands an existing logical volume C<lv> so that it fills
4471 C<pc>% of the remaining free space in the volume group.  Commonly
4472 you would call this with pc = 100 which expands the logical volume
4473 as much as possible, using all remaining free space in the volume
4474 group.");
4475
4476   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4477    [], (* XXX Augeas code needs tests. *)
4478    "clear Augeas path",
4479    "\
4480 Set the value associated with C<path> to C<NULL>.  This
4481 is the same as the L<augtool(1)> C<clear> command.");
4482
4483 ]
4484
4485 let all_functions = non_daemon_functions @ daemon_functions
4486
4487 (* In some places we want the functions to be displayed sorted
4488  * alphabetically, so this is useful:
4489  *)
4490 let all_functions_sorted =
4491   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4492                compare n1 n2) all_functions
4493
4494 (* Field types for structures. *)
4495 type field =
4496   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4497   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4498   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4499   | FUInt32
4500   | FInt32
4501   | FUInt64
4502   | FInt64
4503   | FBytes                      (* Any int measure that counts bytes. *)
4504   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4505   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4506
4507 (* Because we generate extra parsing code for LVM command line tools,
4508  * we have to pull out the LVM columns separately here.
4509  *)
4510 let lvm_pv_cols = [
4511   "pv_name", FString;
4512   "pv_uuid", FUUID;
4513   "pv_fmt", FString;
4514   "pv_size", FBytes;
4515   "dev_size", FBytes;
4516   "pv_free", FBytes;
4517   "pv_used", FBytes;
4518   "pv_attr", FString (* XXX *);
4519   "pv_pe_count", FInt64;
4520   "pv_pe_alloc_count", FInt64;
4521   "pv_tags", FString;
4522   "pe_start", FBytes;
4523   "pv_mda_count", FInt64;
4524   "pv_mda_free", FBytes;
4525   (* Not in Fedora 10:
4526      "pv_mda_size", FBytes;
4527   *)
4528 ]
4529 let lvm_vg_cols = [
4530   "vg_name", FString;
4531   "vg_uuid", FUUID;
4532   "vg_fmt", FString;
4533   "vg_attr", FString (* XXX *);
4534   "vg_size", FBytes;
4535   "vg_free", FBytes;
4536   "vg_sysid", FString;
4537   "vg_extent_size", FBytes;
4538   "vg_extent_count", FInt64;
4539   "vg_free_count", FInt64;
4540   "max_lv", FInt64;
4541   "max_pv", FInt64;
4542   "pv_count", FInt64;
4543   "lv_count", FInt64;
4544   "snap_count", FInt64;
4545   "vg_seqno", FInt64;
4546   "vg_tags", FString;
4547   "vg_mda_count", FInt64;
4548   "vg_mda_free", FBytes;
4549   (* Not in Fedora 10:
4550      "vg_mda_size", FBytes;
4551   *)
4552 ]
4553 let lvm_lv_cols = [
4554   "lv_name", FString;
4555   "lv_uuid", FUUID;
4556   "lv_attr", FString (* XXX *);
4557   "lv_major", FInt64;
4558   "lv_minor", FInt64;
4559   "lv_kernel_major", FInt64;
4560   "lv_kernel_minor", FInt64;
4561   "lv_size", FBytes;
4562   "seg_count", FInt64;
4563   "origin", FString;
4564   "snap_percent", FOptPercent;
4565   "copy_percent", FOptPercent;
4566   "move_pv", FString;
4567   "lv_tags", FString;
4568   "mirror_log", FString;
4569   "modules", FString;
4570 ]
4571
4572 (* Names and fields in all structures (in RStruct and RStructList)
4573  * that we support.
4574  *)
4575 let structs = [
4576   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4577    * not use this struct in any new code.
4578    *)
4579   "int_bool", [
4580     "i", FInt32;                (* for historical compatibility *)
4581     "b", FInt32;                (* for historical compatibility *)
4582   ];
4583
4584   (* LVM PVs, VGs, LVs. *)
4585   "lvm_pv", lvm_pv_cols;
4586   "lvm_vg", lvm_vg_cols;
4587   "lvm_lv", lvm_lv_cols;
4588
4589   (* Column names and types from stat structures.
4590    * NB. Can't use things like 'st_atime' because glibc header files
4591    * define some of these as macros.  Ugh.
4592    *)
4593   "stat", [
4594     "dev", FInt64;
4595     "ino", FInt64;
4596     "mode", FInt64;
4597     "nlink", FInt64;
4598     "uid", FInt64;
4599     "gid", FInt64;
4600     "rdev", FInt64;
4601     "size", FInt64;
4602     "blksize", FInt64;
4603     "blocks", FInt64;
4604     "atime", FInt64;
4605     "mtime", FInt64;
4606     "ctime", FInt64;
4607   ];
4608   "statvfs", [
4609     "bsize", FInt64;
4610     "frsize", FInt64;
4611     "blocks", FInt64;
4612     "bfree", FInt64;
4613     "bavail", FInt64;
4614     "files", FInt64;
4615     "ffree", FInt64;
4616     "favail", FInt64;
4617     "fsid", FInt64;
4618     "flag", FInt64;
4619     "namemax", FInt64;
4620   ];
4621
4622   (* Column names in dirent structure. *)
4623   "dirent", [
4624     "ino", FInt64;
4625     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4626     "ftyp", FChar;
4627     "name", FString;
4628   ];
4629
4630   (* Version numbers. *)
4631   "version", [
4632     "major", FInt64;
4633     "minor", FInt64;
4634     "release", FInt64;
4635     "extra", FString;
4636   ];
4637
4638   (* Extended attribute. *)
4639   "xattr", [
4640     "attrname", FString;
4641     "attrval", FBuffer;
4642   ];
4643
4644   (* Inotify events. *)
4645   "inotify_event", [
4646     "in_wd", FInt64;
4647     "in_mask", FUInt32;
4648     "in_cookie", FUInt32;
4649     "in_name", FString;
4650   ];
4651
4652   (* Partition table entry. *)
4653   "partition", [
4654     "part_num", FInt32;
4655     "part_start", FBytes;
4656     "part_end", FBytes;
4657     "part_size", FBytes;
4658   ];
4659 ] (* end of structs *)
4660
4661 (* Ugh, Java has to be different ..
4662  * These names are also used by the Haskell bindings.
4663  *)
4664 let java_structs = [
4665   "int_bool", "IntBool";
4666   "lvm_pv", "PV";
4667   "lvm_vg", "VG";
4668   "lvm_lv", "LV";
4669   "stat", "Stat";
4670   "statvfs", "StatVFS";
4671   "dirent", "Dirent";
4672   "version", "Version";
4673   "xattr", "XAttr";
4674   "inotify_event", "INotifyEvent";
4675   "partition", "Partition";
4676 ]
4677
4678 (* What structs are actually returned. *)
4679 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4680
4681 (* Returns a list of RStruct/RStructList structs that are returned
4682  * by any function.  Each element of returned list is a pair:
4683  *
4684  * (structname, RStructOnly)
4685  *    == there exists function which returns RStruct (_, structname)
4686  * (structname, RStructListOnly)
4687  *    == there exists function which returns RStructList (_, structname)
4688  * (structname, RStructAndList)
4689  *    == there are functions returning both RStruct (_, structname)
4690  *                                      and RStructList (_, structname)
4691  *)
4692 let rstructs_used_by functions =
4693   (* ||| is a "logical OR" for rstructs_used_t *)
4694   let (|||) a b =
4695     match a, b with
4696     | RStructAndList, _
4697     | _, RStructAndList -> RStructAndList
4698     | RStructOnly, RStructListOnly
4699     | RStructListOnly, RStructOnly -> RStructAndList
4700     | RStructOnly, RStructOnly -> RStructOnly
4701     | RStructListOnly, RStructListOnly -> RStructListOnly
4702   in
4703
4704   let h = Hashtbl.create 13 in
4705
4706   (* if elem->oldv exists, update entry using ||| operator,
4707    * else just add elem->newv to the hash
4708    *)
4709   let update elem newv =
4710     try  let oldv = Hashtbl.find h elem in
4711          Hashtbl.replace h elem (newv ||| oldv)
4712     with Not_found -> Hashtbl.add h elem newv
4713   in
4714
4715   List.iter (
4716     fun (_, style, _, _, _, _, _) ->
4717       match fst style with
4718       | RStruct (_, structname) -> update structname RStructOnly
4719       | RStructList (_, structname) -> update structname RStructListOnly
4720       | _ -> ()
4721   ) functions;
4722
4723   (* return key->values as a list of (key,value) *)
4724   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4725
4726 (* Used for testing language bindings. *)
4727 type callt =
4728   | CallString of string
4729   | CallOptString of string option
4730   | CallStringList of string list
4731   | CallInt of int
4732   | CallInt64 of int64
4733   | CallBool of bool
4734
4735 (* Used to memoize the result of pod2text. *)
4736 let pod2text_memo_filename = "src/.pod2text.data"
4737 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4738   try
4739     let chan = open_in pod2text_memo_filename in
4740     let v = input_value chan in
4741     close_in chan;
4742     v
4743   with
4744     _ -> Hashtbl.create 13
4745 let pod2text_memo_updated () =
4746   let chan = open_out pod2text_memo_filename in
4747   output_value chan pod2text_memo;
4748   close_out chan
4749
4750 (* Useful functions.
4751  * Note we don't want to use any external OCaml libraries which
4752  * makes this a bit harder than it should be.
4753  *)
4754 module StringMap = Map.Make (String)
4755
4756 let failwithf fs = ksprintf failwith fs
4757
4758 let unique = let i = ref 0 in fun () -> incr i; !i
4759
4760 let replace_char s c1 c2 =
4761   let s2 = String.copy s in
4762   let r = ref false in
4763   for i = 0 to String.length s2 - 1 do
4764     if String.unsafe_get s2 i = c1 then (
4765       String.unsafe_set s2 i c2;
4766       r := true
4767     )
4768   done;
4769   if not !r then s else s2
4770
4771 let isspace c =
4772   c = ' '
4773   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4774
4775 let triml ?(test = isspace) str =
4776   let i = ref 0 in
4777   let n = ref (String.length str) in
4778   while !n > 0 && test str.[!i]; do
4779     decr n;
4780     incr i
4781   done;
4782   if !i = 0 then str
4783   else String.sub str !i !n
4784
4785 let trimr ?(test = isspace) str =
4786   let n = ref (String.length str) in
4787   while !n > 0 && test str.[!n-1]; do
4788     decr n
4789   done;
4790   if !n = String.length str then str
4791   else String.sub str 0 !n
4792
4793 let trim ?(test = isspace) str =
4794   trimr ~test (triml ~test str)
4795
4796 let rec find s sub =
4797   let len = String.length s in
4798   let sublen = String.length sub in
4799   let rec loop i =
4800     if i <= len-sublen then (
4801       let rec loop2 j =
4802         if j < sublen then (
4803           if s.[i+j] = sub.[j] then loop2 (j+1)
4804           else -1
4805         ) else
4806           i (* found *)
4807       in
4808       let r = loop2 0 in
4809       if r = -1 then loop (i+1) else r
4810     ) else
4811       -1 (* not found *)
4812   in
4813   loop 0
4814
4815 let rec replace_str s s1 s2 =
4816   let len = String.length s in
4817   let sublen = String.length s1 in
4818   let i = find s s1 in
4819   if i = -1 then s
4820   else (
4821     let s' = String.sub s 0 i in
4822     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4823     s' ^ s2 ^ replace_str s'' s1 s2
4824   )
4825
4826 let rec string_split sep str =
4827   let len = String.length str in
4828   let seplen = String.length sep in
4829   let i = find str sep in
4830   if i = -1 then [str]
4831   else (
4832     let s' = String.sub str 0 i in
4833     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4834     s' :: string_split sep s''
4835   )
4836
4837 let files_equal n1 n2 =
4838   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4839   match Sys.command cmd with
4840   | 0 -> true
4841   | 1 -> false
4842   | i -> failwithf "%s: failed with error code %d" cmd i
4843
4844 let rec filter_map f = function
4845   | [] -> []
4846   | x :: xs ->
4847       match f x with
4848       | Some y -> y :: filter_map f xs
4849       | None -> filter_map f xs
4850
4851 let rec find_map f = function
4852   | [] -> raise Not_found
4853   | x :: xs ->
4854       match f x with
4855       | Some y -> y
4856       | None -> find_map f xs
4857
4858 let iteri f xs =
4859   let rec loop i = function
4860     | [] -> ()
4861     | x :: xs -> f i x; loop (i+1) xs
4862   in
4863   loop 0 xs
4864
4865 let mapi f xs =
4866   let rec loop i = function
4867     | [] -> []
4868     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4869   in
4870   loop 0 xs
4871
4872 let count_chars c str =
4873   let count = ref 0 in
4874   for i = 0 to String.length str - 1 do
4875     if c = String.unsafe_get str i then incr count
4876   done;
4877   !count
4878
4879 let name_of_argt = function
4880   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4881   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4882   | FileIn n | FileOut n -> n
4883
4884 let java_name_of_struct typ =
4885   try List.assoc typ java_structs
4886   with Not_found ->
4887     failwithf
4888       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4889
4890 let cols_of_struct typ =
4891   try List.assoc typ structs
4892   with Not_found ->
4893     failwithf "cols_of_struct: unknown struct %s" typ
4894
4895 let seq_of_test = function
4896   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4897   | TestOutputListOfDevices (s, _)
4898   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4899   | TestOutputTrue s | TestOutputFalse s
4900   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4901   | TestOutputStruct (s, _)
4902   | TestLastFail s -> s
4903
4904 (* Handling for function flags. *)
4905 let protocol_limit_warning =
4906   "Because of the message protocol, there is a transfer limit
4907 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4908
4909 let danger_will_robinson =
4910   "B<This command is dangerous.  Without careful use you
4911 can easily destroy all your data>."
4912
4913 let deprecation_notice flags =
4914   try
4915     let alt =
4916       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4917     let txt =
4918       sprintf "This function is deprecated.
4919 In new code, use the C<%s> call instead.
4920
4921 Deprecated functions will not be removed from the API, but the
4922 fact that they are deprecated indicates that there are problems
4923 with correct use of these functions." alt in
4924     Some txt
4925   with
4926     Not_found -> None
4927
4928 (* Create list of optional groups. *)
4929 let optgroups =
4930   let h = Hashtbl.create 13 in
4931   List.iter (
4932     fun (name, _, _, flags, _, _, _) ->
4933       List.iter (
4934         function
4935         | Optional group ->
4936             let names = try Hashtbl.find h group with Not_found -> [] in
4937             Hashtbl.replace h group (name :: names)
4938         | _ -> ()
4939       ) flags
4940   ) daemon_functions;
4941   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4942   let groups =
4943     List.map (
4944       fun group -> group, List.sort compare (Hashtbl.find h group)
4945     ) groups in
4946   List.sort (fun x y -> compare (fst x) (fst y)) groups
4947
4948 (* Check function names etc. for consistency. *)
4949 let check_functions () =
4950   let contains_uppercase str =
4951     let len = String.length str in
4952     let rec loop i =
4953       if i >= len then false
4954       else (
4955         let c = str.[i] in
4956         if c >= 'A' && c <= 'Z' then true
4957         else loop (i+1)
4958       )
4959     in
4960     loop 0
4961   in
4962
4963   (* Check function names. *)
4964   List.iter (
4965     fun (name, _, _, _, _, _, _) ->
4966       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4967         failwithf "function name %s does not need 'guestfs' prefix" name;
4968       if name = "" then
4969         failwithf "function name is empty";
4970       if name.[0] < 'a' || name.[0] > 'z' then
4971         failwithf "function name %s must start with lowercase a-z" name;
4972       if String.contains name '-' then
4973         failwithf "function name %s should not contain '-', use '_' instead."
4974           name
4975   ) all_functions;
4976
4977   (* Check function parameter/return names. *)
4978   List.iter (
4979     fun (name, style, _, _, _, _, _) ->
4980       let check_arg_ret_name n =
4981         if contains_uppercase n then
4982           failwithf "%s param/ret %s should not contain uppercase chars"
4983             name n;
4984         if String.contains n '-' || String.contains n '_' then
4985           failwithf "%s param/ret %s should not contain '-' or '_'"
4986             name n;
4987         if n = "value" then
4988           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;
4989         if n = "int" || n = "char" || n = "short" || n = "long" then
4990           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4991         if n = "i" || n = "n" then
4992           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4993         if n = "argv" || n = "args" then
4994           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4995
4996         (* List Haskell, OCaml and C keywords here.
4997          * http://www.haskell.org/haskellwiki/Keywords
4998          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4999          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5000          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5001          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5002          * Omitting _-containing words, since they're handled above.
5003          * Omitting the OCaml reserved word, "val", is ok,
5004          * and saves us from renaming several parameters.
5005          *)
5006         let reserved = [
5007           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5008           "char"; "class"; "const"; "constraint"; "continue"; "data";
5009           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5010           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5011           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5012           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5013           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5014           "interface";
5015           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5016           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5017           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5018           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5019           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5020           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5021           "volatile"; "when"; "where"; "while";
5022           ] in
5023         if List.mem n reserved then
5024           failwithf "%s has param/ret using reserved word %s" name n;
5025       in
5026
5027       (match fst style with
5028        | RErr -> ()
5029        | RInt n | RInt64 n | RBool n
5030        | RConstString n | RConstOptString n | RString n
5031        | RStringList n | RStruct (n, _) | RStructList (n, _)
5032        | RHashtable n | RBufferOut n ->
5033            check_arg_ret_name n
5034       );
5035       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5036   ) all_functions;
5037
5038   (* Check short descriptions. *)
5039   List.iter (
5040     fun (name, _, _, _, _, shortdesc, _) ->
5041       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5042         failwithf "short description of %s should begin with lowercase." name;
5043       let c = shortdesc.[String.length shortdesc-1] in
5044       if c = '\n' || c = '.' then
5045         failwithf "short description of %s should not end with . or \\n." name
5046   ) all_functions;
5047
5048   (* Check long dscriptions. *)
5049   List.iter (
5050     fun (name, _, _, _, _, _, longdesc) ->
5051       if longdesc.[String.length longdesc-1] = '\n' then
5052         failwithf "long description of %s should not end with \\n." name
5053   ) all_functions;
5054
5055   (* Check proc_nrs. *)
5056   List.iter (
5057     fun (name, _, proc_nr, _, _, _, _) ->
5058       if proc_nr <= 0 then
5059         failwithf "daemon function %s should have proc_nr > 0" name
5060   ) daemon_functions;
5061
5062   List.iter (
5063     fun (name, _, proc_nr, _, _, _, _) ->
5064       if proc_nr <> -1 then
5065         failwithf "non-daemon function %s should have proc_nr -1" name
5066   ) non_daemon_functions;
5067
5068   let proc_nrs =
5069     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5070       daemon_functions in
5071   let proc_nrs =
5072     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5073   let rec loop = function
5074     | [] -> ()
5075     | [_] -> ()
5076     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5077         loop rest
5078     | (name1,nr1) :: (name2,nr2) :: _ ->
5079         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5080           name1 name2 nr1 nr2
5081   in
5082   loop proc_nrs;
5083
5084   (* Check tests. *)
5085   List.iter (
5086     function
5087       (* Ignore functions that have no tests.  We generate a
5088        * warning when the user does 'make check' instead.
5089        *)
5090     | name, _, _, _, [], _, _ -> ()
5091     | name, _, _, _, tests, _, _ ->
5092         let funcs =
5093           List.map (
5094             fun (_, _, test) ->
5095               match seq_of_test test with
5096               | [] ->
5097                   failwithf "%s has a test containing an empty sequence" name
5098               | cmds -> List.map List.hd cmds
5099           ) tests in
5100         let funcs = List.flatten funcs in
5101
5102         let tested = List.mem name funcs in
5103
5104         if not tested then
5105           failwithf "function %s has tests but does not test itself" name
5106   ) all_functions
5107
5108 (* 'pr' prints to the current output file. *)
5109 let chan = ref Pervasives.stdout
5110 let lines = ref 0
5111 let pr fs =
5112   ksprintf
5113     (fun str ->
5114        let i = count_chars '\n' str in
5115        lines := !lines + i;
5116        output_string !chan str
5117     ) fs
5118
5119 let copyright_years =
5120   let this_year = 1900 + (localtime (time ())).tm_year in
5121   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5122
5123 (* Generate a header block in a number of standard styles. *)
5124 type comment_style =
5125     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5126 type license = GPLv2plus | LGPLv2plus
5127
5128 let generate_header ?(extra_inputs = []) comment license =
5129   let inputs = "src/generator.ml" :: extra_inputs in
5130   let c = match comment with
5131     | CStyle ->         pr "/* "; " *"
5132     | CPlusPlusStyle -> pr "// "; "//"
5133     | HashStyle ->      pr "# ";  "#"
5134     | OCamlStyle ->     pr "(* "; " *"
5135     | HaskellStyle ->   pr "{- "; "  " in
5136   pr "libguestfs generated file\n";
5137   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5138   List.iter (pr "%s   %s\n" c) inputs;
5139   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5140   pr "%s\n" c;
5141   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5142   pr "%s\n" c;
5143   (match license with
5144    | GPLv2plus ->
5145        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5146        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5147        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5148        pr "%s (at your option) any later version.\n" c;
5149        pr "%s\n" c;
5150        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5151        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5152        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5153        pr "%s GNU General Public License for more details.\n" c;
5154        pr "%s\n" c;
5155        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5156        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5157        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5158
5159    | LGPLv2plus ->
5160        pr "%s This library is free software; you can redistribute it and/or\n" c;
5161        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5162        pr "%s License as published by the Free Software Foundation; either\n" c;
5163        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5164        pr "%s\n" c;
5165        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5166        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5167        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5168        pr "%s Lesser General Public License for more details.\n" c;
5169        pr "%s\n" c;
5170        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5171        pr "%s License along with this library; if not, write to the Free Software\n" c;
5172        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5173   );
5174   (match comment with
5175    | CStyle -> pr " */\n"
5176    | CPlusPlusStyle
5177    | HashStyle -> ()
5178    | OCamlStyle -> pr " *)\n"
5179    | HaskellStyle -> pr "-}\n"
5180   );
5181   pr "\n"
5182
5183 (* Start of main code generation functions below this line. *)
5184
5185 (* Generate the pod documentation for the C API. *)
5186 let rec generate_actions_pod () =
5187   List.iter (
5188     fun (shortname, style, _, flags, _, _, longdesc) ->
5189       if not (List.mem NotInDocs flags) then (
5190         let name = "guestfs_" ^ shortname in
5191         pr "=head2 %s\n\n" name;
5192         pr " ";
5193         generate_prototype ~extern:false ~handle:"handle" name style;
5194         pr "\n\n";
5195         pr "%s\n\n" longdesc;
5196         (match fst style with
5197          | RErr ->
5198              pr "This function returns 0 on success or -1 on error.\n\n"
5199          | RInt _ ->
5200              pr "On error this function returns -1.\n\n"
5201          | RInt64 _ ->
5202              pr "On error this function returns -1.\n\n"
5203          | RBool _ ->
5204              pr "This function returns a C truth value on success or -1 on error.\n\n"
5205          | RConstString _ ->
5206              pr "This function returns a string, or NULL on error.
5207 The string is owned by the guest handle and must I<not> be freed.\n\n"
5208          | RConstOptString _ ->
5209              pr "This function returns a string which may be NULL.
5210 There is way to return an error from this function.
5211 The string is owned by the guest handle and must I<not> be freed.\n\n"
5212          | RString _ ->
5213              pr "This function returns a string, or NULL on error.
5214 I<The caller must free the returned string after use>.\n\n"
5215          | RStringList _ ->
5216              pr "This function returns a NULL-terminated array of strings
5217 (like L<environ(3)>), or NULL if there was an error.
5218 I<The caller must free the strings and the array after use>.\n\n"
5219          | RStruct (_, typ) ->
5220              pr "This function returns a C<struct guestfs_%s *>,
5221 or NULL if there was an error.
5222 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5223          | RStructList (_, typ) ->
5224              pr "This function returns a C<struct guestfs_%s_list *>
5225 (see E<lt>guestfs-structs.hE<gt>),
5226 or NULL if there was an error.
5227 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5228          | RHashtable _ ->
5229              pr "This function returns a NULL-terminated array of
5230 strings, or NULL if there was an error.
5231 The array of strings will always have length C<2n+1>, where
5232 C<n> keys and values alternate, followed by the trailing NULL entry.
5233 I<The caller must free the strings and the array after use>.\n\n"
5234          | RBufferOut _ ->
5235              pr "This function returns a buffer, or NULL on error.
5236 The size of the returned buffer is written to C<*size_r>.
5237 I<The caller must free the returned buffer after use>.\n\n"
5238         );
5239         if List.mem ProtocolLimitWarning flags then
5240           pr "%s\n\n" protocol_limit_warning;
5241         if List.mem DangerWillRobinson flags then
5242           pr "%s\n\n" danger_will_robinson;
5243         match deprecation_notice flags with
5244         | None -> ()
5245         | Some txt -> pr "%s\n\n" txt
5246       )
5247   ) all_functions_sorted
5248
5249 and generate_structs_pod () =
5250   (* Structs documentation. *)
5251   List.iter (
5252     fun (typ, cols) ->
5253       pr "=head2 guestfs_%s\n" typ;
5254       pr "\n";
5255       pr " struct guestfs_%s {\n" typ;
5256       List.iter (
5257         function
5258         | name, FChar -> pr "   char %s;\n" name
5259         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5260         | name, FInt32 -> pr "   int32_t %s;\n" name
5261         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5262         | name, FInt64 -> pr "   int64_t %s;\n" name
5263         | name, FString -> pr "   char *%s;\n" name
5264         | name, FBuffer ->
5265             pr "   /* The next two fields describe a byte array. */\n";
5266             pr "   uint32_t %s_len;\n" name;
5267             pr "   char *%s;\n" name
5268         | name, FUUID ->
5269             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5270             pr "   char %s[32];\n" name
5271         | name, FOptPercent ->
5272             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5273             pr "   float %s;\n" name
5274       ) cols;
5275       pr " };\n";
5276       pr " \n";
5277       pr " struct guestfs_%s_list {\n" typ;
5278       pr "   uint32_t len; /* Number of elements in list. */\n";
5279       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5280       pr " };\n";
5281       pr " \n";
5282       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5283       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5284         typ typ;
5285       pr "\n"
5286   ) structs
5287
5288 and generate_availability_pod () =
5289   (* Availability documentation. *)
5290   pr "=over 4\n";
5291   pr "\n";
5292   List.iter (
5293     fun (group, functions) ->
5294       pr "=item B<%s>\n" group;
5295       pr "\n";
5296       pr "The following functions:\n";
5297       List.iter (pr "L</guestfs_%s>\n") functions;
5298       pr "\n"
5299   ) optgroups;
5300   pr "=back\n";
5301   pr "\n"
5302
5303 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5304  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5305  *
5306  * We have to use an underscore instead of a dash because otherwise
5307  * rpcgen generates incorrect code.
5308  *
5309  * This header is NOT exported to clients, but see also generate_structs_h.
5310  *)
5311 and generate_xdr () =
5312   generate_header CStyle LGPLv2plus;
5313
5314   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5315   pr "typedef string str<>;\n";
5316   pr "\n";
5317
5318   (* Internal structures. *)
5319   List.iter (
5320     function
5321     | typ, cols ->
5322         pr "struct guestfs_int_%s {\n" typ;
5323         List.iter (function
5324                    | name, FChar -> pr "  char %s;\n" name
5325                    | name, FString -> pr "  string %s<>;\n" name
5326                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5327                    | name, FUUID -> pr "  opaque %s[32];\n" name
5328                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5329                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5330                    | name, FOptPercent -> pr "  float %s;\n" name
5331                   ) cols;
5332         pr "};\n";
5333         pr "\n";
5334         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5335         pr "\n";
5336   ) structs;
5337
5338   List.iter (
5339     fun (shortname, style, _, _, _, _, _) ->
5340       let name = "guestfs_" ^ shortname in
5341
5342       (match snd style with
5343        | [] -> ()
5344        | args ->
5345            pr "struct %s_args {\n" name;
5346            List.iter (
5347              function
5348              | Pathname n | Device n | Dev_or_Path n | String n ->
5349                  pr "  string %s<>;\n" n
5350              | OptString n -> pr "  str *%s;\n" n
5351              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5352              | Bool n -> pr "  bool %s;\n" n
5353              | Int n -> pr "  int %s;\n" n
5354              | Int64 n -> pr "  hyper %s;\n" n
5355              | FileIn _ | FileOut _ -> ()
5356            ) args;
5357            pr "};\n\n"
5358       );
5359       (match fst style with
5360        | RErr -> ()
5361        | RInt n ->
5362            pr "struct %s_ret {\n" name;
5363            pr "  int %s;\n" n;
5364            pr "};\n\n"
5365        | RInt64 n ->
5366            pr "struct %s_ret {\n" name;
5367            pr "  hyper %s;\n" n;
5368            pr "};\n\n"
5369        | RBool n ->
5370            pr "struct %s_ret {\n" name;
5371            pr "  bool %s;\n" n;
5372            pr "};\n\n"
5373        | RConstString _ | RConstOptString _ ->
5374            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5375        | RString n ->
5376            pr "struct %s_ret {\n" name;
5377            pr "  string %s<>;\n" n;
5378            pr "};\n\n"
5379        | RStringList n ->
5380            pr "struct %s_ret {\n" name;
5381            pr "  str %s<>;\n" n;
5382            pr "};\n\n"
5383        | RStruct (n, typ) ->
5384            pr "struct %s_ret {\n" name;
5385            pr "  guestfs_int_%s %s;\n" typ n;
5386            pr "};\n\n"
5387        | RStructList (n, typ) ->
5388            pr "struct %s_ret {\n" name;
5389            pr "  guestfs_int_%s_list %s;\n" typ n;
5390            pr "};\n\n"
5391        | RHashtable n ->
5392            pr "struct %s_ret {\n" name;
5393            pr "  str %s<>;\n" n;
5394            pr "};\n\n"
5395        | RBufferOut n ->
5396            pr "struct %s_ret {\n" name;
5397            pr "  opaque %s<>;\n" n;
5398            pr "};\n\n"
5399       );
5400   ) daemon_functions;
5401
5402   (* Table of procedure numbers. *)
5403   pr "enum guestfs_procedure {\n";
5404   List.iter (
5405     fun (shortname, _, proc_nr, _, _, _, _) ->
5406       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5407   ) daemon_functions;
5408   pr "  GUESTFS_PROC_NR_PROCS\n";
5409   pr "};\n";
5410   pr "\n";
5411
5412   (* Having to choose a maximum message size is annoying for several
5413    * reasons (it limits what we can do in the API), but it (a) makes
5414    * the protocol a lot simpler, and (b) provides a bound on the size
5415    * of the daemon which operates in limited memory space.
5416    *)
5417   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5418   pr "\n";
5419
5420   (* Message header, etc. *)
5421   pr "\
5422 /* The communication protocol is now documented in the guestfs(3)
5423  * manpage.
5424  */
5425
5426 const GUESTFS_PROGRAM = 0x2000F5F5;
5427 const GUESTFS_PROTOCOL_VERSION = 1;
5428
5429 /* These constants must be larger than any possible message length. */
5430 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5431 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5432
5433 enum guestfs_message_direction {
5434   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5435   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5436 };
5437
5438 enum guestfs_message_status {
5439   GUESTFS_STATUS_OK = 0,
5440   GUESTFS_STATUS_ERROR = 1
5441 };
5442
5443 const GUESTFS_ERROR_LEN = 256;
5444
5445 struct guestfs_message_error {
5446   string error_message<GUESTFS_ERROR_LEN>;
5447 };
5448
5449 struct guestfs_message_header {
5450   unsigned prog;                     /* GUESTFS_PROGRAM */
5451   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5452   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5453   guestfs_message_direction direction;
5454   unsigned serial;                   /* message serial number */
5455   guestfs_message_status status;
5456 };
5457
5458 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5459
5460 struct guestfs_chunk {
5461   int cancel;                        /* if non-zero, transfer is cancelled */
5462   /* data size is 0 bytes if the transfer has finished successfully */
5463   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5464 };
5465 "
5466
5467 (* Generate the guestfs-structs.h file. *)
5468 and generate_structs_h () =
5469   generate_header CStyle LGPLv2plus;
5470
5471   (* This is a public exported header file containing various
5472    * structures.  The structures are carefully written to have
5473    * exactly the same in-memory format as the XDR structures that
5474    * we use on the wire to the daemon.  The reason for creating
5475    * copies of these structures here is just so we don't have to
5476    * export the whole of guestfs_protocol.h (which includes much
5477    * unrelated and XDR-dependent stuff that we don't want to be
5478    * public, or required by clients).
5479    *
5480    * To reiterate, we will pass these structures to and from the
5481    * client with a simple assignment or memcpy, so the format
5482    * must be identical to what rpcgen / the RFC defines.
5483    *)
5484
5485   (* Public structures. *)
5486   List.iter (
5487     fun (typ, cols) ->
5488       pr "struct guestfs_%s {\n" typ;
5489       List.iter (
5490         function
5491         | name, FChar -> pr "  char %s;\n" name
5492         | name, FString -> pr "  char *%s;\n" name
5493         | name, FBuffer ->
5494             pr "  uint32_t %s_len;\n" name;
5495             pr "  char *%s;\n" name
5496         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5497         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5498         | name, FInt32 -> pr "  int32_t %s;\n" name
5499         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5500         | name, FInt64 -> pr "  int64_t %s;\n" name
5501         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5502       ) cols;
5503       pr "};\n";
5504       pr "\n";
5505       pr "struct guestfs_%s_list {\n" typ;
5506       pr "  uint32_t len;\n";
5507       pr "  struct guestfs_%s *val;\n" typ;
5508       pr "};\n";
5509       pr "\n";
5510       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5511       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5512       pr "\n"
5513   ) structs
5514
5515 (* Generate the guestfs-actions.h file. *)
5516 and generate_actions_h () =
5517   generate_header CStyle LGPLv2plus;
5518   List.iter (
5519     fun (shortname, style, _, _, _, _, _) ->
5520       let name = "guestfs_" ^ shortname in
5521       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5522         name style
5523   ) all_functions
5524
5525 (* Generate the guestfs-internal-actions.h file. *)
5526 and generate_internal_actions_h () =
5527   generate_header CStyle LGPLv2plus;
5528   List.iter (
5529     fun (shortname, style, _, _, _, _, _) ->
5530       let name = "guestfs__" ^ shortname in
5531       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5532         name style
5533   ) non_daemon_functions
5534
5535 (* Generate the client-side dispatch stubs. *)
5536 and generate_client_actions () =
5537   generate_header CStyle LGPLv2plus;
5538
5539   pr "\
5540 #include <stdio.h>
5541 #include <stdlib.h>
5542 #include <stdint.h>
5543 #include <string.h>
5544 #include <inttypes.h>
5545
5546 #include \"guestfs.h\"
5547 #include \"guestfs-internal.h\"
5548 #include \"guestfs-internal-actions.h\"
5549 #include \"guestfs_protocol.h\"
5550
5551 #define error guestfs_error
5552 //#define perrorf guestfs_perrorf
5553 #define safe_malloc guestfs_safe_malloc
5554 #define safe_realloc guestfs_safe_realloc
5555 //#define safe_strdup guestfs_safe_strdup
5556 #define safe_memdup guestfs_safe_memdup
5557
5558 /* Check the return message from a call for validity. */
5559 static int
5560 check_reply_header (guestfs_h *g,
5561                     const struct guestfs_message_header *hdr,
5562                     unsigned int proc_nr, unsigned int serial)
5563 {
5564   if (hdr->prog != GUESTFS_PROGRAM) {
5565     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5566     return -1;
5567   }
5568   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5569     error (g, \"wrong protocol version (%%d/%%d)\",
5570            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5571     return -1;
5572   }
5573   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5574     error (g, \"unexpected message direction (%%d/%%d)\",
5575            hdr->direction, GUESTFS_DIRECTION_REPLY);
5576     return -1;
5577   }
5578   if (hdr->proc != proc_nr) {
5579     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5580     return -1;
5581   }
5582   if (hdr->serial != serial) {
5583     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5584     return -1;
5585   }
5586
5587   return 0;
5588 }
5589
5590 /* Check we are in the right state to run a high-level action. */
5591 static int
5592 check_state (guestfs_h *g, const char *caller)
5593 {
5594   if (!guestfs__is_ready (g)) {
5595     if (guestfs__is_config (g) || guestfs__is_launching (g))
5596       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5597         caller);
5598     else
5599       error (g, \"%%s called from the wrong state, %%d != READY\",
5600         caller, guestfs__get_state (g));
5601     return -1;
5602   }
5603   return 0;
5604 }
5605
5606 ";
5607
5608   (* Generate code to generate guestfish call traces. *)
5609   let trace_call shortname style =
5610     pr "  if (guestfs__get_trace (g)) {\n";
5611
5612     let needs_i =
5613       List.exists (function
5614                    | StringList _ | DeviceList _ -> true
5615                    | _ -> false) (snd style) in
5616     if needs_i then (
5617       pr "    int i;\n";
5618       pr "\n"
5619     );
5620
5621     pr "    printf (\"%s\");\n" shortname;
5622     List.iter (
5623       function
5624       | String n                        (* strings *)
5625       | Device n
5626       | Pathname n
5627       | Dev_or_Path n
5628       | FileIn n
5629       | FileOut n ->
5630           (* guestfish doesn't support string escaping, so neither do we *)
5631           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5632       | OptString n ->                  (* string option *)
5633           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5634           pr "    else printf (\" null\");\n"
5635       | StringList n
5636       | DeviceList n ->                 (* string list *)
5637           pr "    putchar (' ');\n";
5638           pr "    putchar ('\"');\n";
5639           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5640           pr "      if (i > 0) putchar (' ');\n";
5641           pr "      fputs (%s[i], stdout);\n" n;
5642           pr "    }\n";
5643           pr "    putchar ('\"');\n";
5644       | Bool n ->                       (* boolean *)
5645           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5646       | Int n ->                        (* int *)
5647           pr "    printf (\" %%d\", %s);\n" n
5648       | Int64 n ->
5649           pr "    printf (\" %%\" PRIi64, %s);\n" n
5650     ) (snd style);
5651     pr "    putchar ('\\n');\n";
5652     pr "  }\n";
5653     pr "\n";
5654   in
5655
5656   (* For non-daemon functions, generate a wrapper around each function. *)
5657   List.iter (
5658     fun (shortname, style, _, _, _, _, _) ->
5659       let name = "guestfs_" ^ shortname in
5660
5661       generate_prototype ~extern:false ~semicolon:false ~newline:true
5662         ~handle:"g" name style;
5663       pr "{\n";
5664       trace_call shortname style;
5665       pr "  return guestfs__%s " shortname;
5666       generate_c_call_args ~handle:"g" style;
5667       pr ";\n";
5668       pr "}\n";
5669       pr "\n"
5670   ) non_daemon_functions;
5671
5672   (* Client-side stubs for each function. *)
5673   List.iter (
5674     fun (shortname, style, _, _, _, _, _) ->
5675       let name = "guestfs_" ^ shortname in
5676
5677       (* Generate the action stub. *)
5678       generate_prototype ~extern:false ~semicolon:false ~newline:true
5679         ~handle:"g" name style;
5680
5681       let error_code =
5682         match fst style with
5683         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5684         | RConstString _ | RConstOptString _ ->
5685             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5686         | RString _ | RStringList _
5687         | RStruct _ | RStructList _
5688         | RHashtable _ | RBufferOut _ ->
5689             "NULL" in
5690
5691       pr "{\n";
5692
5693       (match snd style with
5694        | [] -> ()
5695        | _ -> pr "  struct %s_args args;\n" name
5696       );
5697
5698       pr "  guestfs_message_header hdr;\n";
5699       pr "  guestfs_message_error err;\n";
5700       let has_ret =
5701         match fst style with
5702         | RErr -> false
5703         | RConstString _ | RConstOptString _ ->
5704             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5705         | RInt _ | RInt64 _
5706         | RBool _ | RString _ | RStringList _
5707         | RStruct _ | RStructList _
5708         | RHashtable _ | RBufferOut _ ->
5709             pr "  struct %s_ret ret;\n" name;
5710             true in
5711
5712       pr "  int serial;\n";
5713       pr "  int r;\n";
5714       pr "\n";
5715       trace_call shortname style;
5716       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5717       pr "  guestfs___set_busy (g);\n";
5718       pr "\n";
5719
5720       (* Send the main header and arguments. *)
5721       (match snd style with
5722        | [] ->
5723            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5724              (String.uppercase shortname)
5725        | args ->
5726            List.iter (
5727              function
5728              | Pathname n | Device n | Dev_or_Path n | String n ->
5729                  pr "  args.%s = (char *) %s;\n" n n
5730              | OptString n ->
5731                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5732              | StringList n | DeviceList n ->
5733                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5734                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5735              | Bool n ->
5736                  pr "  args.%s = %s;\n" n n
5737              | Int n ->
5738                  pr "  args.%s = %s;\n" n n
5739              | Int64 n ->
5740                  pr "  args.%s = %s;\n" n n
5741              | FileIn _ | FileOut _ -> ()
5742            ) args;
5743            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5744              (String.uppercase shortname);
5745            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5746              name;
5747       );
5748       pr "  if (serial == -1) {\n";
5749       pr "    guestfs___end_busy (g);\n";
5750       pr "    return %s;\n" error_code;
5751       pr "  }\n";
5752       pr "\n";
5753
5754       (* Send any additional files (FileIn) requested. *)
5755       let need_read_reply_label = ref false in
5756       List.iter (
5757         function
5758         | FileIn n ->
5759             pr "  r = guestfs___send_file (g, %s);\n" n;
5760             pr "  if (r == -1) {\n";
5761             pr "    guestfs___end_busy (g);\n";
5762             pr "    return %s;\n" error_code;
5763             pr "  }\n";
5764             pr "  if (r == -2) /* daemon cancelled */\n";
5765             pr "    goto read_reply;\n";
5766             need_read_reply_label := true;
5767             pr "\n";
5768         | _ -> ()
5769       ) (snd style);
5770
5771       (* Wait for the reply from the remote end. *)
5772       if !need_read_reply_label then pr " read_reply:\n";
5773       pr "  memset (&hdr, 0, sizeof hdr);\n";
5774       pr "  memset (&err, 0, sizeof err);\n";
5775       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5776       pr "\n";
5777       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5778       if not has_ret then
5779         pr "NULL, NULL"
5780       else
5781         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5782       pr ");\n";
5783
5784       pr "  if (r == -1) {\n";
5785       pr "    guestfs___end_busy (g);\n";
5786       pr "    return %s;\n" error_code;
5787       pr "  }\n";
5788       pr "\n";
5789
5790       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5791         (String.uppercase shortname);
5792       pr "    guestfs___end_busy (g);\n";
5793       pr "    return %s;\n" error_code;
5794       pr "  }\n";
5795       pr "\n";
5796
5797       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5798       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5799       pr "    free (err.error_message);\n";
5800       pr "    guestfs___end_busy (g);\n";
5801       pr "    return %s;\n" error_code;
5802       pr "  }\n";
5803       pr "\n";
5804
5805       (* Expecting to receive further files (FileOut)? *)
5806       List.iter (
5807         function
5808         | FileOut n ->
5809             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5810             pr "    guestfs___end_busy (g);\n";
5811             pr "    return %s;\n" error_code;
5812             pr "  }\n";
5813             pr "\n";
5814         | _ -> ()
5815       ) (snd style);
5816
5817       pr "  guestfs___end_busy (g);\n";
5818
5819       (match fst style with
5820        | RErr -> pr "  return 0;\n"
5821        | RInt n | RInt64 n | RBool n ->
5822            pr "  return ret.%s;\n" n
5823        | RConstString _ | RConstOptString _ ->
5824            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5825        | RString n ->
5826            pr "  return ret.%s; /* caller will free */\n" n
5827        | RStringList n | RHashtable n ->
5828            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5829            pr "  ret.%s.%s_val =\n" n n;
5830            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5831            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5832              n n;
5833            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5834            pr "  return ret.%s.%s_val;\n" n n
5835        | RStruct (n, _) ->
5836            pr "  /* caller will free this */\n";
5837            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5838        | RStructList (n, _) ->
5839            pr "  /* caller will free this */\n";
5840            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5841        | RBufferOut n ->
5842            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5843            pr "   * _val might be NULL here.  To make the API saner for\n";
5844            pr "   * callers, we turn this case into a unique pointer (using\n";
5845            pr "   * malloc(1)).\n";
5846            pr "   */\n";
5847            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5848            pr "    *size_r = ret.%s.%s_len;\n" n n;
5849            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5850            pr "  } else {\n";
5851            pr "    free (ret.%s.%s_val);\n" n n;
5852            pr "    char *p = safe_malloc (g, 1);\n";
5853            pr "    *size_r = ret.%s.%s_len;\n" n n;
5854            pr "    return p;\n";
5855            pr "  }\n";
5856       );
5857
5858       pr "}\n\n"
5859   ) daemon_functions;
5860
5861   (* Functions to free structures. *)
5862   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5863   pr " * structure format is identical to the XDR format.  See note in\n";
5864   pr " * generator.ml.\n";
5865   pr " */\n";
5866   pr "\n";
5867
5868   List.iter (
5869     fun (typ, _) ->
5870       pr "void\n";
5871       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5872       pr "{\n";
5873       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5874       pr "  free (x);\n";
5875       pr "}\n";
5876       pr "\n";
5877
5878       pr "void\n";
5879       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5880       pr "{\n";
5881       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5882       pr "  free (x);\n";
5883       pr "}\n";
5884       pr "\n";
5885
5886   ) structs;
5887
5888 (* Generate daemon/actions.h. *)
5889 and generate_daemon_actions_h () =
5890   generate_header CStyle GPLv2plus;
5891
5892   pr "#include \"../src/guestfs_protocol.h\"\n";
5893   pr "\n";
5894
5895   List.iter (
5896     fun (name, style, _, _, _, _, _) ->
5897       generate_prototype
5898         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5899         name style;
5900   ) daemon_functions
5901
5902 (* Generate the linker script which controls the visibility of
5903  * symbols in the public ABI and ensures no other symbols get
5904  * exported accidentally.
5905  *)
5906 and generate_linker_script () =
5907   generate_header HashStyle GPLv2plus;
5908
5909   let globals = [
5910     "guestfs_create";
5911     "guestfs_close";
5912     "guestfs_get_error_handler";
5913     "guestfs_get_out_of_memory_handler";
5914     "guestfs_last_error";
5915     "guestfs_set_error_handler";
5916     "guestfs_set_launch_done_callback";
5917     "guestfs_set_log_message_callback";
5918     "guestfs_set_out_of_memory_handler";
5919     "guestfs_set_subprocess_quit_callback";
5920
5921     (* Unofficial parts of the API: the bindings code use these
5922      * functions, so it is useful to export them.
5923      *)
5924     "guestfs_safe_calloc";
5925     "guestfs_safe_malloc";
5926   ] in
5927   let functions =
5928     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5929       all_functions in
5930   let structs =
5931     List.concat (
5932       List.map (fun (typ, _) ->
5933                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5934         structs
5935     ) in
5936   let globals = List.sort compare (globals @ functions @ structs) in
5937
5938   pr "{\n";
5939   pr "    global:\n";
5940   List.iter (pr "        %s;\n") globals;
5941   pr "\n";
5942
5943   pr "    local:\n";
5944   pr "        *;\n";
5945   pr "};\n"
5946
5947 (* Generate the server-side stubs. *)
5948 and generate_daemon_actions () =
5949   generate_header CStyle GPLv2plus;
5950
5951   pr "#include <config.h>\n";
5952   pr "\n";
5953   pr "#include <stdio.h>\n";
5954   pr "#include <stdlib.h>\n";
5955   pr "#include <string.h>\n";
5956   pr "#include <inttypes.h>\n";
5957   pr "#include <rpc/types.h>\n";
5958   pr "#include <rpc/xdr.h>\n";
5959   pr "\n";
5960   pr "#include \"daemon.h\"\n";
5961   pr "#include \"c-ctype.h\"\n";
5962   pr "#include \"../src/guestfs_protocol.h\"\n";
5963   pr "#include \"actions.h\"\n";
5964   pr "\n";
5965
5966   List.iter (
5967     fun (name, style, _, _, _, _, _) ->
5968       (* Generate server-side stubs. *)
5969       pr "static void %s_stub (XDR *xdr_in)\n" name;
5970       pr "{\n";
5971       let error_code =
5972         match fst style with
5973         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5974         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5975         | RBool _ -> pr "  int r;\n"; "-1"
5976         | RConstString _ | RConstOptString _ ->
5977             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5978         | RString _ -> pr "  char *r;\n"; "NULL"
5979         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5980         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5981         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5982         | RBufferOut _ ->
5983             pr "  size_t size = 1;\n";
5984             pr "  char *r;\n";
5985             "NULL" in
5986
5987       (match snd style with
5988        | [] -> ()
5989        | args ->
5990            pr "  struct guestfs_%s_args args;\n" name;
5991            List.iter (
5992              function
5993              | Device n | Dev_or_Path n
5994              | Pathname n
5995              | String n -> ()
5996              | OptString n -> pr "  char *%s;\n" n
5997              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5998              | Bool n -> pr "  int %s;\n" n
5999              | Int n -> pr "  int %s;\n" n
6000              | Int64 n -> pr "  int64_t %s;\n" n
6001              | FileIn _ | FileOut _ -> ()
6002            ) args
6003       );
6004       pr "\n";
6005
6006       (match snd style with
6007        | [] -> ()
6008        | args ->
6009            pr "  memset (&args, 0, sizeof args);\n";
6010            pr "\n";
6011            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6012            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6013            pr "    return;\n";
6014            pr "  }\n";
6015            let pr_args n =
6016              pr "  char *%s = args.%s;\n" n n
6017            in
6018            let pr_list_handling_code n =
6019              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6020              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6021              pr "  if (%s == NULL) {\n" n;
6022              pr "    reply_with_perror (\"realloc\");\n";
6023              pr "    goto done;\n";
6024              pr "  }\n";
6025              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6026              pr "  args.%s.%s_val = %s;\n" n n n;
6027            in
6028            List.iter (
6029              function
6030              | Pathname n ->
6031                  pr_args n;
6032                  pr "  ABS_PATH (%s, goto done);\n" n;
6033              | Device n ->
6034                  pr_args n;
6035                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6036              | Dev_or_Path n ->
6037                  pr_args n;
6038                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6039              | String n -> pr_args n
6040              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6041              | StringList n ->
6042                  pr_list_handling_code n;
6043              | DeviceList n ->
6044                  pr_list_handling_code n;
6045                  pr "  /* Ensure that each is a device,\n";
6046                  pr "   * and perform device name translation. */\n";
6047                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6048                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6049                  pr "  }\n";
6050              | Bool n -> pr "  %s = args.%s;\n" n n
6051              | Int n -> pr "  %s = args.%s;\n" n n
6052              | Int64 n -> pr "  %s = args.%s;\n" n n
6053              | FileIn _ | FileOut _ -> ()
6054            ) args;
6055            pr "\n"
6056       );
6057
6058
6059       (* this is used at least for do_equal *)
6060       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6061         (* Emit NEED_ROOT just once, even when there are two or
6062            more Pathname args *)
6063         pr "  NEED_ROOT (goto done);\n";
6064       );
6065
6066       (* Don't want to call the impl with any FileIn or FileOut
6067        * parameters, since these go "outside" the RPC protocol.
6068        *)
6069       let args' =
6070         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6071           (snd style) in
6072       pr "  r = do_%s " name;
6073       generate_c_call_args (fst style, args');
6074       pr ";\n";
6075
6076       (match fst style with
6077        | RErr | RInt _ | RInt64 _ | RBool _
6078        | RConstString _ | RConstOptString _
6079        | RString _ | RStringList _ | RHashtable _
6080        | RStruct (_, _) | RStructList (_, _) ->
6081            pr "  if (r == %s)\n" error_code;
6082            pr "    /* do_%s has already called reply_with_error */\n" name;
6083            pr "    goto done;\n";
6084            pr "\n"
6085        | RBufferOut _ ->
6086            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6087            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6088            pr "   */\n";
6089            pr "  if (size == 1 && r == %s)\n" error_code;
6090            pr "    /* do_%s has already called reply_with_error */\n" name;
6091            pr "    goto done;\n";
6092            pr "\n"
6093       );
6094
6095       (* If there are any FileOut parameters, then the impl must
6096        * send its own reply.
6097        *)
6098       let no_reply =
6099         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6100       if no_reply then
6101         pr "  /* do_%s has already sent a reply */\n" name
6102       else (
6103         match fst style with
6104         | RErr -> pr "  reply (NULL, NULL);\n"
6105         | RInt n | RInt64 n | RBool n ->
6106             pr "  struct guestfs_%s_ret ret;\n" name;
6107             pr "  ret.%s = r;\n" n;
6108             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6109               name
6110         | RConstString _ | RConstOptString _ ->
6111             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6112         | RString n ->
6113             pr "  struct guestfs_%s_ret ret;\n" name;
6114             pr "  ret.%s = r;\n" n;
6115             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6116               name;
6117             pr "  free (r);\n"
6118         | RStringList n | RHashtable n ->
6119             pr "  struct guestfs_%s_ret ret;\n" name;
6120             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6121             pr "  ret.%s.%s_val = r;\n" n n;
6122             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6123               name;
6124             pr "  free_strings (r);\n"
6125         | RStruct (n, _) ->
6126             pr "  struct guestfs_%s_ret ret;\n" name;
6127             pr "  ret.%s = *r;\n" n;
6128             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6129               name;
6130             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6131               name
6132         | RStructList (n, _) ->
6133             pr "  struct guestfs_%s_ret ret;\n" name;
6134             pr "  ret.%s = *r;\n" n;
6135             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6136               name;
6137             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6138               name
6139         | RBufferOut n ->
6140             pr "  struct guestfs_%s_ret ret;\n" name;
6141             pr "  ret.%s.%s_val = r;\n" n n;
6142             pr "  ret.%s.%s_len = size;\n" n n;
6143             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6144               name;
6145             pr "  free (r);\n"
6146       );
6147
6148       (* Free the args. *)
6149       (match snd style with
6150        | [] ->
6151            pr "done: ;\n";
6152        | _ ->
6153            pr "done:\n";
6154            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6155              name
6156       );
6157
6158       pr "}\n\n";
6159   ) daemon_functions;
6160
6161   (* Dispatch function. *)
6162   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6163   pr "{\n";
6164   pr "  switch (proc_nr) {\n";
6165
6166   List.iter (
6167     fun (name, style, _, _, _, _, _) ->
6168       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6169       pr "      %s_stub (xdr_in);\n" name;
6170       pr "      break;\n"
6171   ) daemon_functions;
6172
6173   pr "    default:\n";
6174   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";
6175   pr "  }\n";
6176   pr "}\n";
6177   pr "\n";
6178
6179   (* LVM columns and tokenization functions. *)
6180   (* XXX This generates crap code.  We should rethink how we
6181    * do this parsing.
6182    *)
6183   List.iter (
6184     function
6185     | typ, cols ->
6186         pr "static const char *lvm_%s_cols = \"%s\";\n"
6187           typ (String.concat "," (List.map fst cols));
6188         pr "\n";
6189
6190         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6191         pr "{\n";
6192         pr "  char *tok, *p, *next;\n";
6193         pr "  int i, j;\n";
6194         pr "\n";
6195         (*
6196           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6197           pr "\n";
6198         *)
6199         pr "  if (!str) {\n";
6200         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6201         pr "    return -1;\n";
6202         pr "  }\n";
6203         pr "  if (!*str || c_isspace (*str)) {\n";
6204         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6205         pr "    return -1;\n";
6206         pr "  }\n";
6207         pr "  tok = str;\n";
6208         List.iter (
6209           fun (name, coltype) ->
6210             pr "  if (!tok) {\n";
6211             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6212             pr "    return -1;\n";
6213             pr "  }\n";
6214             pr "  p = strchrnul (tok, ',');\n";
6215             pr "  if (*p) next = p+1; else next = NULL;\n";
6216             pr "  *p = '\\0';\n";
6217             (match coltype with
6218              | FString ->
6219                  pr "  r->%s = strdup (tok);\n" name;
6220                  pr "  if (r->%s == NULL) {\n" name;
6221                  pr "    perror (\"strdup\");\n";
6222                  pr "    return -1;\n";
6223                  pr "  }\n"
6224              | FUUID ->
6225                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6226                  pr "    if (tok[j] == '\\0') {\n";
6227                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6228                  pr "      return -1;\n";
6229                  pr "    } else if (tok[j] != '-')\n";
6230                  pr "      r->%s[i++] = tok[j];\n" name;
6231                  pr "  }\n";
6232              | FBytes ->
6233                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6234                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6235                  pr "    return -1;\n";
6236                  pr "  }\n";
6237              | FInt64 ->
6238                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6239                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6240                  pr "    return -1;\n";
6241                  pr "  }\n";
6242              | FOptPercent ->
6243                  pr "  if (tok[0] == '\\0')\n";
6244                  pr "    r->%s = -1;\n" name;
6245                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6246                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6247                  pr "    return -1;\n";
6248                  pr "  }\n";
6249              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6250                  assert false (* can never be an LVM column *)
6251             );
6252             pr "  tok = next;\n";
6253         ) cols;
6254
6255         pr "  if (tok != NULL) {\n";
6256         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6257         pr "    return -1;\n";
6258         pr "  }\n";
6259         pr "  return 0;\n";
6260         pr "}\n";
6261         pr "\n";
6262
6263         pr "guestfs_int_lvm_%s_list *\n" typ;
6264         pr "parse_command_line_%ss (void)\n" typ;
6265         pr "{\n";
6266         pr "  char *out, *err;\n";
6267         pr "  char *p, *pend;\n";
6268         pr "  int r, i;\n";
6269         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6270         pr "  void *newp;\n";
6271         pr "\n";
6272         pr "  ret = malloc (sizeof *ret);\n";
6273         pr "  if (!ret) {\n";
6274         pr "    reply_with_perror (\"malloc\");\n";
6275         pr "    return NULL;\n";
6276         pr "  }\n";
6277         pr "\n";
6278         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6279         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6280         pr "\n";
6281         pr "  r = command (&out, &err,\n";
6282         pr "           \"lvm\", \"%ss\",\n" typ;
6283         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6284         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6285         pr "  if (r == -1) {\n";
6286         pr "    reply_with_error (\"%%s\", err);\n";
6287         pr "    free (out);\n";
6288         pr "    free (err);\n";
6289         pr "    free (ret);\n";
6290         pr "    return NULL;\n";
6291         pr "  }\n";
6292         pr "\n";
6293         pr "  free (err);\n";
6294         pr "\n";
6295         pr "  /* Tokenize each line of the output. */\n";
6296         pr "  p = out;\n";
6297         pr "  i = 0;\n";
6298         pr "  while (p) {\n";
6299         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6300         pr "    if (pend) {\n";
6301         pr "      *pend = '\\0';\n";
6302         pr "      pend++;\n";
6303         pr "    }\n";
6304         pr "\n";
6305         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6306         pr "      p++;\n";
6307         pr "\n";
6308         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6309         pr "      p = pend;\n";
6310         pr "      continue;\n";
6311         pr "    }\n";
6312         pr "\n";
6313         pr "    /* Allocate some space to store this next entry. */\n";
6314         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6315         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6316         pr "    if (newp == NULL) {\n";
6317         pr "      reply_with_perror (\"realloc\");\n";
6318         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6319         pr "      free (ret);\n";
6320         pr "      free (out);\n";
6321         pr "      return NULL;\n";
6322         pr "    }\n";
6323         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6324         pr "\n";
6325         pr "    /* Tokenize the next entry. */\n";
6326         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6327         pr "    if (r == -1) {\n";
6328         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6329         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6330         pr "      free (ret);\n";
6331         pr "      free (out);\n";
6332         pr "      return NULL;\n";
6333         pr "    }\n";
6334         pr "\n";
6335         pr "    ++i;\n";
6336         pr "    p = pend;\n";
6337         pr "  }\n";
6338         pr "\n";
6339         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6340         pr "\n";
6341         pr "  free (out);\n";
6342         pr "  return ret;\n";
6343         pr "}\n"
6344
6345   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6346
6347 (* Generate a list of function names, for debugging in the daemon.. *)
6348 and generate_daemon_names () =
6349   generate_header CStyle GPLv2plus;
6350
6351   pr "#include <config.h>\n";
6352   pr "\n";
6353   pr "#include \"daemon.h\"\n";
6354   pr "\n";
6355
6356   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6357   pr "const char *function_names[] = {\n";
6358   List.iter (
6359     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6360   ) daemon_functions;
6361   pr "};\n";
6362
6363 (* Generate the optional groups for the daemon to implement
6364  * guestfs_available.
6365  *)
6366 and generate_daemon_optgroups_c () =
6367   generate_header CStyle GPLv2plus;
6368
6369   pr "#include <config.h>\n";
6370   pr "\n";
6371   pr "#include \"daemon.h\"\n";
6372   pr "#include \"optgroups.h\"\n";
6373   pr "\n";
6374
6375   pr "struct optgroup optgroups[] = {\n";
6376   List.iter (
6377     fun (group, _) ->
6378       pr "  { \"%s\", optgroup_%s_available },\n" group group
6379   ) optgroups;
6380   pr "  { NULL, NULL }\n";
6381   pr "};\n"
6382
6383 and generate_daemon_optgroups_h () =
6384   generate_header CStyle GPLv2plus;
6385
6386   List.iter (
6387     fun (group, _) ->
6388       pr "extern int optgroup_%s_available (void);\n" group
6389   ) optgroups
6390
6391 (* Generate the tests. *)
6392 and generate_tests () =
6393   generate_header CStyle GPLv2plus;
6394
6395   pr "\
6396 #include <stdio.h>
6397 #include <stdlib.h>
6398 #include <string.h>
6399 #include <unistd.h>
6400 #include <sys/types.h>
6401 #include <fcntl.h>
6402
6403 #include \"guestfs.h\"
6404 #include \"guestfs-internal.h\"
6405
6406 static guestfs_h *g;
6407 static int suppress_error = 0;
6408
6409 static void print_error (guestfs_h *g, void *data, const char *msg)
6410 {
6411   if (!suppress_error)
6412     fprintf (stderr, \"%%s\\n\", msg);
6413 }
6414
6415 /* FIXME: nearly identical code appears in fish.c */
6416 static void print_strings (char *const *argv)
6417 {
6418   int argc;
6419
6420   for (argc = 0; argv[argc] != NULL; ++argc)
6421     printf (\"\\t%%s\\n\", argv[argc]);
6422 }
6423
6424 /*
6425 static void print_table (char const *const *argv)
6426 {
6427   int i;
6428
6429   for (i = 0; argv[i] != NULL; i += 2)
6430     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6431 }
6432 */
6433
6434 ";
6435
6436   (* Generate a list of commands which are not tested anywhere. *)
6437   pr "static void no_test_warnings (void)\n";
6438   pr "{\n";
6439
6440   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6441   List.iter (
6442     fun (_, _, _, _, tests, _, _) ->
6443       let tests = filter_map (
6444         function
6445         | (_, (Always|If _|Unless _), test) -> Some test
6446         | (_, Disabled, _) -> None
6447       ) tests in
6448       let seq = List.concat (List.map seq_of_test tests) in
6449       let cmds_tested = List.map List.hd seq in
6450       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6451   ) all_functions;
6452
6453   List.iter (
6454     fun (name, _, _, _, _, _, _) ->
6455       if not (Hashtbl.mem hash name) then
6456         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6457   ) all_functions;
6458
6459   pr "}\n";
6460   pr "\n";
6461
6462   (* Generate the actual tests.  Note that we generate the tests
6463    * in reverse order, deliberately, so that (in general) the
6464    * newest tests run first.  This makes it quicker and easier to
6465    * debug them.
6466    *)
6467   let test_names =
6468     List.map (
6469       fun (name, _, _, flags, tests, _, _) ->
6470         mapi (generate_one_test name flags) tests
6471     ) (List.rev all_functions) in
6472   let test_names = List.concat test_names in
6473   let nr_tests = List.length test_names in
6474
6475   pr "\
6476 int main (int argc, char *argv[])
6477 {
6478   char c = 0;
6479   unsigned long int n_failed = 0;
6480   const char *filename;
6481   int fd;
6482   int nr_tests, test_num = 0;
6483
6484   setbuf (stdout, NULL);
6485
6486   no_test_warnings ();
6487
6488   g = guestfs_create ();
6489   if (g == NULL) {
6490     printf (\"guestfs_create FAILED\\n\");
6491     exit (EXIT_FAILURE);
6492   }
6493
6494   guestfs_set_error_handler (g, print_error, NULL);
6495
6496   guestfs_set_path (g, \"../appliance\");
6497
6498   filename = \"test1.img\";
6499   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6500   if (fd == -1) {
6501     perror (filename);
6502     exit (EXIT_FAILURE);
6503   }
6504   if (lseek (fd, %d, SEEK_SET) == -1) {
6505     perror (\"lseek\");
6506     close (fd);
6507     unlink (filename);
6508     exit (EXIT_FAILURE);
6509   }
6510   if (write (fd, &c, 1) == -1) {
6511     perror (\"write\");
6512     close (fd);
6513     unlink (filename);
6514     exit (EXIT_FAILURE);
6515   }
6516   if (close (fd) == -1) {
6517     perror (filename);
6518     unlink (filename);
6519     exit (EXIT_FAILURE);
6520   }
6521   if (guestfs_add_drive (g, filename) == -1) {
6522     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6523     exit (EXIT_FAILURE);
6524   }
6525
6526   filename = \"test2.img\";
6527   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6528   if (fd == -1) {
6529     perror (filename);
6530     exit (EXIT_FAILURE);
6531   }
6532   if (lseek (fd, %d, SEEK_SET) == -1) {
6533     perror (\"lseek\");
6534     close (fd);
6535     unlink (filename);
6536     exit (EXIT_FAILURE);
6537   }
6538   if (write (fd, &c, 1) == -1) {
6539     perror (\"write\");
6540     close (fd);
6541     unlink (filename);
6542     exit (EXIT_FAILURE);
6543   }
6544   if (close (fd) == -1) {
6545     perror (filename);
6546     unlink (filename);
6547     exit (EXIT_FAILURE);
6548   }
6549   if (guestfs_add_drive (g, filename) == -1) {
6550     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6551     exit (EXIT_FAILURE);
6552   }
6553
6554   filename = \"test3.img\";
6555   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6556   if (fd == -1) {
6557     perror (filename);
6558     exit (EXIT_FAILURE);
6559   }
6560   if (lseek (fd, %d, SEEK_SET) == -1) {
6561     perror (\"lseek\");
6562     close (fd);
6563     unlink (filename);
6564     exit (EXIT_FAILURE);
6565   }
6566   if (write (fd, &c, 1) == -1) {
6567     perror (\"write\");
6568     close (fd);
6569     unlink (filename);
6570     exit (EXIT_FAILURE);
6571   }
6572   if (close (fd) == -1) {
6573     perror (filename);
6574     unlink (filename);
6575     exit (EXIT_FAILURE);
6576   }
6577   if (guestfs_add_drive (g, filename) == -1) {
6578     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6579     exit (EXIT_FAILURE);
6580   }
6581
6582   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6583     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6584     exit (EXIT_FAILURE);
6585   }
6586
6587   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6588   alarm (600);
6589
6590   if (guestfs_launch (g) == -1) {
6591     printf (\"guestfs_launch FAILED\\n\");
6592     exit (EXIT_FAILURE);
6593   }
6594
6595   /* Cancel previous alarm. */
6596   alarm (0);
6597
6598   nr_tests = %d;
6599
6600 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6601
6602   iteri (
6603     fun i test_name ->
6604       pr "  test_num++;\n";
6605       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6606       pr "  if (%s () == -1) {\n" test_name;
6607       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6608       pr "    n_failed++;\n";
6609       pr "  }\n";
6610   ) test_names;
6611   pr "\n";
6612
6613   pr "  guestfs_close (g);\n";
6614   pr "  unlink (\"test1.img\");\n";
6615   pr "  unlink (\"test2.img\");\n";
6616   pr "  unlink (\"test3.img\");\n";
6617   pr "\n";
6618
6619   pr "  if (n_failed > 0) {\n";
6620   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6621   pr "    exit (EXIT_FAILURE);\n";
6622   pr "  }\n";
6623   pr "\n";
6624
6625   pr "  exit (EXIT_SUCCESS);\n";
6626   pr "}\n"
6627
6628 and generate_one_test name flags i (init, prereq, test) =
6629   let test_name = sprintf "test_%s_%d" name i in
6630
6631   pr "\
6632 static int %s_skip (void)
6633 {
6634   const char *str;
6635
6636   str = getenv (\"TEST_ONLY\");
6637   if (str)
6638     return strstr (str, \"%s\") == NULL;
6639   str = getenv (\"SKIP_%s\");
6640   if (str && STREQ (str, \"1\")) return 1;
6641   str = getenv (\"SKIP_TEST_%s\");
6642   if (str && STREQ (str, \"1\")) return 1;
6643   return 0;
6644 }
6645
6646 " test_name name (String.uppercase test_name) (String.uppercase name);
6647
6648   (match prereq with
6649    | Disabled | Always -> ()
6650    | If code | Unless code ->
6651        pr "static int %s_prereq (void)\n" test_name;
6652        pr "{\n";
6653        pr "  %s\n" code;
6654        pr "}\n";
6655        pr "\n";
6656   );
6657
6658   pr "\
6659 static int %s (void)
6660 {
6661   if (%s_skip ()) {
6662     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6663     return 0;
6664   }
6665
6666 " test_name test_name test_name;
6667
6668   (* Optional functions should only be tested if the relevant
6669    * support is available in the daemon.
6670    *)
6671   List.iter (
6672     function
6673     | Optional group ->
6674         pr "  {\n";
6675         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6676         pr "    int r;\n";
6677         pr "    suppress_error = 1;\n";
6678         pr "    r = guestfs_available (g, (char **) groups);\n";
6679         pr "    suppress_error = 0;\n";
6680         pr "    if (r == -1) {\n";
6681         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6682         pr "      return 0;\n";
6683         pr "    }\n";
6684         pr "  }\n";
6685     | _ -> ()
6686   ) flags;
6687
6688   (match prereq with
6689    | Disabled ->
6690        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6691    | If _ ->
6692        pr "  if (! %s_prereq ()) {\n" test_name;
6693        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6694        pr "    return 0;\n";
6695        pr "  }\n";
6696        pr "\n";
6697        generate_one_test_body name i test_name init test;
6698    | Unless _ ->
6699        pr "  if (%s_prereq ()) {\n" test_name;
6700        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6701        pr "    return 0;\n";
6702        pr "  }\n";
6703        pr "\n";
6704        generate_one_test_body name i test_name init test;
6705    | Always ->
6706        generate_one_test_body name i test_name init test
6707   );
6708
6709   pr "  return 0;\n";
6710   pr "}\n";
6711   pr "\n";
6712   test_name
6713
6714 and generate_one_test_body name i test_name init test =
6715   (match init with
6716    | InitNone (* XXX at some point, InitNone and InitEmpty became
6717                * folded together as the same thing.  Really we should
6718                * make InitNone do nothing at all, but the tests may
6719                * need to be checked to make sure this is OK.
6720                *)
6721    | InitEmpty ->
6722        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6723        List.iter (generate_test_command_call test_name)
6724          [["blockdev_setrw"; "/dev/sda"];
6725           ["umount_all"];
6726           ["lvm_remove_all"]]
6727    | InitPartition ->
6728        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6729        List.iter (generate_test_command_call test_name)
6730          [["blockdev_setrw"; "/dev/sda"];
6731           ["umount_all"];
6732           ["lvm_remove_all"];
6733           ["part_disk"; "/dev/sda"; "mbr"]]
6734    | InitBasicFS ->
6735        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6736        List.iter (generate_test_command_call test_name)
6737          [["blockdev_setrw"; "/dev/sda"];
6738           ["umount_all"];
6739           ["lvm_remove_all"];
6740           ["part_disk"; "/dev/sda"; "mbr"];
6741           ["mkfs"; "ext2"; "/dev/sda1"];
6742           ["mount_options"; ""; "/dev/sda1"; "/"]]
6743    | InitBasicFSonLVM ->
6744        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6745          test_name;
6746        List.iter (generate_test_command_call test_name)
6747          [["blockdev_setrw"; "/dev/sda"];
6748           ["umount_all"];
6749           ["lvm_remove_all"];
6750           ["part_disk"; "/dev/sda"; "mbr"];
6751           ["pvcreate"; "/dev/sda1"];
6752           ["vgcreate"; "VG"; "/dev/sda1"];
6753           ["lvcreate"; "LV"; "VG"; "8"];
6754           ["mkfs"; "ext2"; "/dev/VG/LV"];
6755           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6756    | InitISOFS ->
6757        pr "  /* InitISOFS for %s */\n" test_name;
6758        List.iter (generate_test_command_call test_name)
6759          [["blockdev_setrw"; "/dev/sda"];
6760           ["umount_all"];
6761           ["lvm_remove_all"];
6762           ["mount_ro"; "/dev/sdd"; "/"]]
6763   );
6764
6765   let get_seq_last = function
6766     | [] ->
6767         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6768           test_name
6769     | seq ->
6770         let seq = List.rev seq in
6771         List.rev (List.tl seq), List.hd seq
6772   in
6773
6774   match test with
6775   | TestRun seq ->
6776       pr "  /* TestRun for %s (%d) */\n" name i;
6777       List.iter (generate_test_command_call test_name) seq
6778   | TestOutput (seq, expected) ->
6779       pr "  /* TestOutput for %s (%d) */\n" name i;
6780       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6781       let seq, last = get_seq_last seq in
6782       let test () =
6783         pr "    if (STRNEQ (r, expected)) {\n";
6784         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6785         pr "      return -1;\n";
6786         pr "    }\n"
6787       in
6788       List.iter (generate_test_command_call test_name) seq;
6789       generate_test_command_call ~test test_name last
6790   | TestOutputList (seq, expected) ->
6791       pr "  /* TestOutputList for %s (%d) */\n" name i;
6792       let seq, last = get_seq_last seq in
6793       let test () =
6794         iteri (
6795           fun i str ->
6796             pr "    if (!r[%d]) {\n" i;
6797             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6798             pr "      print_strings (r);\n";
6799             pr "      return -1;\n";
6800             pr "    }\n";
6801             pr "    {\n";
6802             pr "      const char *expected = \"%s\";\n" (c_quote str);
6803             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6804             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6805             pr "        return -1;\n";
6806             pr "      }\n";
6807             pr "    }\n"
6808         ) expected;
6809         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6810         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6811           test_name;
6812         pr "      print_strings (r);\n";
6813         pr "      return -1;\n";
6814         pr "    }\n"
6815       in
6816       List.iter (generate_test_command_call test_name) seq;
6817       generate_test_command_call ~test test_name last
6818   | TestOutputListOfDevices (seq, expected) ->
6819       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6820       let seq, last = get_seq_last seq in
6821       let test () =
6822         iteri (
6823           fun i str ->
6824             pr "    if (!r[%d]) {\n" i;
6825             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6826             pr "      print_strings (r);\n";
6827             pr "      return -1;\n";
6828             pr "    }\n";
6829             pr "    {\n";
6830             pr "      const char *expected = \"%s\";\n" (c_quote str);
6831             pr "      r[%d][5] = 's';\n" i;
6832             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6833             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6834             pr "        return -1;\n";
6835             pr "      }\n";
6836             pr "    }\n"
6837         ) expected;
6838         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6839         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6840           test_name;
6841         pr "      print_strings (r);\n";
6842         pr "      return -1;\n";
6843         pr "    }\n"
6844       in
6845       List.iter (generate_test_command_call test_name) seq;
6846       generate_test_command_call ~test test_name last
6847   | TestOutputInt (seq, expected) ->
6848       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6849       let seq, last = get_seq_last seq in
6850       let test () =
6851         pr "    if (r != %d) {\n" expected;
6852         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6853           test_name expected;
6854         pr "               (int) r);\n";
6855         pr "      return -1;\n";
6856         pr "    }\n"
6857       in
6858       List.iter (generate_test_command_call test_name) seq;
6859       generate_test_command_call ~test test_name last
6860   | TestOutputIntOp (seq, op, expected) ->
6861       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6862       let seq, last = get_seq_last seq in
6863       let test () =
6864         pr "    if (! (r %s %d)) {\n" op expected;
6865         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6866           test_name op expected;
6867         pr "               (int) r);\n";
6868         pr "      return -1;\n";
6869         pr "    }\n"
6870       in
6871       List.iter (generate_test_command_call test_name) seq;
6872       generate_test_command_call ~test test_name last
6873   | TestOutputTrue seq ->
6874       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6875       let seq, last = get_seq_last seq in
6876       let test () =
6877         pr "    if (!r) {\n";
6878         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6879           test_name;
6880         pr "      return -1;\n";
6881         pr "    }\n"
6882       in
6883       List.iter (generate_test_command_call test_name) seq;
6884       generate_test_command_call ~test test_name last
6885   | TestOutputFalse seq ->
6886       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6887       let seq, last = get_seq_last seq in
6888       let test () =
6889         pr "    if (r) {\n";
6890         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6891           test_name;
6892         pr "      return -1;\n";
6893         pr "    }\n"
6894       in
6895       List.iter (generate_test_command_call test_name) seq;
6896       generate_test_command_call ~test test_name last
6897   | TestOutputLength (seq, expected) ->
6898       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6899       let seq, last = get_seq_last seq in
6900       let test () =
6901         pr "    int j;\n";
6902         pr "    for (j = 0; j < %d; ++j)\n" expected;
6903         pr "      if (r[j] == NULL) {\n";
6904         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6905           test_name;
6906         pr "        print_strings (r);\n";
6907         pr "        return -1;\n";
6908         pr "      }\n";
6909         pr "    if (r[j] != NULL) {\n";
6910         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6911           test_name;
6912         pr "      print_strings (r);\n";
6913         pr "      return -1;\n";
6914         pr "    }\n"
6915       in
6916       List.iter (generate_test_command_call test_name) seq;
6917       generate_test_command_call ~test test_name last
6918   | TestOutputBuffer (seq, expected) ->
6919       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6920       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6921       let seq, last = get_seq_last seq in
6922       let len = String.length expected in
6923       let test () =
6924         pr "    if (size != %d) {\n" len;
6925         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6926         pr "      return -1;\n";
6927         pr "    }\n";
6928         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6929         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6930         pr "      return -1;\n";
6931         pr "    }\n"
6932       in
6933       List.iter (generate_test_command_call test_name) seq;
6934       generate_test_command_call ~test test_name last
6935   | TestOutputStruct (seq, checks) ->
6936       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6937       let seq, last = get_seq_last seq in
6938       let test () =
6939         List.iter (
6940           function
6941           | CompareWithInt (field, expected) ->
6942               pr "    if (r->%s != %d) {\n" field expected;
6943               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6944                 test_name field expected;
6945               pr "               (int) r->%s);\n" field;
6946               pr "      return -1;\n";
6947               pr "    }\n"
6948           | CompareWithIntOp (field, op, expected) ->
6949               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6950               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6951                 test_name field op expected;
6952               pr "               (int) r->%s);\n" field;
6953               pr "      return -1;\n";
6954               pr "    }\n"
6955           | CompareWithString (field, expected) ->
6956               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6957               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6958                 test_name field expected;
6959               pr "               r->%s);\n" field;
6960               pr "      return -1;\n";
6961               pr "    }\n"
6962           | CompareFieldsIntEq (field1, field2) ->
6963               pr "    if (r->%s != r->%s) {\n" field1 field2;
6964               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6965                 test_name field1 field2;
6966               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6967               pr "      return -1;\n";
6968               pr "    }\n"
6969           | CompareFieldsStrEq (field1, field2) ->
6970               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6971               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6972                 test_name field1 field2;
6973               pr "               r->%s, r->%s);\n" field1 field2;
6974               pr "      return -1;\n";
6975               pr "    }\n"
6976         ) checks
6977       in
6978       List.iter (generate_test_command_call test_name) seq;
6979       generate_test_command_call ~test test_name last
6980   | TestLastFail seq ->
6981       pr "  /* TestLastFail for %s (%d) */\n" name i;
6982       let seq, last = get_seq_last seq in
6983       List.iter (generate_test_command_call test_name) seq;
6984       generate_test_command_call test_name ~expect_error:true last
6985
6986 (* Generate the code to run a command, leaving the result in 'r'.
6987  * If you expect to get an error then you should set expect_error:true.
6988  *)
6989 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6990   match cmd with
6991   | [] -> assert false
6992   | name :: args ->
6993       (* Look up the command to find out what args/ret it has. *)
6994       let style =
6995         try
6996           let _, style, _, _, _, _, _ =
6997             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6998           style
6999         with Not_found ->
7000           failwithf "%s: in test, command %s was not found" test_name name in
7001
7002       if List.length (snd style) <> List.length args then
7003         failwithf "%s: in test, wrong number of args given to %s"
7004           test_name name;
7005
7006       pr "  {\n";
7007
7008       List.iter (
7009         function
7010         | OptString n, "NULL" -> ()
7011         | Pathname n, arg
7012         | Device n, arg
7013         | Dev_or_Path n, arg
7014         | String n, arg
7015         | OptString n, arg ->
7016             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7017         | Int _, _
7018         | Int64 _, _
7019         | Bool _, _
7020         | FileIn _, _ | FileOut _, _ -> ()
7021         | StringList n, "" | DeviceList n, "" ->
7022             pr "    const char *const %s[1] = { NULL };\n" n
7023         | StringList n, arg | DeviceList n, arg ->
7024             let strs = string_split " " arg in
7025             iteri (
7026               fun i str ->
7027                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7028             ) strs;
7029             pr "    const char *const %s[] = {\n" n;
7030             iteri (
7031               fun i _ -> pr "      %s_%d,\n" n i
7032             ) strs;
7033             pr "      NULL\n";
7034             pr "    };\n";
7035       ) (List.combine (snd style) args);
7036
7037       let error_code =
7038         match fst style with
7039         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7040         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7041         | RConstString _ | RConstOptString _ ->
7042             pr "    const char *r;\n"; "NULL"
7043         | RString _ -> pr "    char *r;\n"; "NULL"
7044         | RStringList _ | RHashtable _ ->
7045             pr "    char **r;\n";
7046             pr "    int i;\n";
7047             "NULL"
7048         | RStruct (_, typ) ->
7049             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7050         | RStructList (_, typ) ->
7051             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7052         | RBufferOut _ ->
7053             pr "    char *r;\n";
7054             pr "    size_t size;\n";
7055             "NULL" in
7056
7057       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7058       pr "    r = guestfs_%s (g" name;
7059
7060       (* Generate the parameters. *)
7061       List.iter (
7062         function
7063         | OptString _, "NULL" -> pr ", NULL"
7064         | Pathname n, _
7065         | Device n, _ | Dev_or_Path n, _
7066         | String n, _
7067         | OptString n, _ ->
7068             pr ", %s" n
7069         | FileIn _, arg | FileOut _, arg ->
7070             pr ", \"%s\"" (c_quote arg)
7071         | StringList n, _ | DeviceList n, _ ->
7072             pr ", (char **) %s" n
7073         | Int _, arg ->
7074             let i =
7075               try int_of_string arg
7076               with Failure "int_of_string" ->
7077                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7078             pr ", %d" i
7079         | Int64 _, arg ->
7080             let i =
7081               try Int64.of_string arg
7082               with Failure "int_of_string" ->
7083                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7084             pr ", %Ld" i
7085         | Bool _, arg ->
7086             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7087       ) (List.combine (snd style) args);
7088
7089       (match fst style with
7090        | RBufferOut _ -> pr ", &size"
7091        | _ -> ()
7092       );
7093
7094       pr ");\n";
7095
7096       if not expect_error then
7097         pr "    if (r == %s)\n" error_code
7098       else
7099         pr "    if (r != %s)\n" error_code;
7100       pr "      return -1;\n";
7101
7102       (* Insert the test code. *)
7103       (match test with
7104        | None -> ()
7105        | Some f -> f ()
7106       );
7107
7108       (match fst style with
7109        | RErr | RInt _ | RInt64 _ | RBool _
7110        | RConstString _ | RConstOptString _ -> ()
7111        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7112        | RStringList _ | RHashtable _ ->
7113            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7114            pr "      free (r[i]);\n";
7115            pr "    free (r);\n"
7116        | RStruct (_, typ) ->
7117            pr "    guestfs_free_%s (r);\n" typ
7118        | RStructList (_, typ) ->
7119            pr "    guestfs_free_%s_list (r);\n" typ
7120       );
7121
7122       pr "  }\n"
7123
7124 and c_quote str =
7125   let str = replace_str str "\r" "\\r" in
7126   let str = replace_str str "\n" "\\n" in
7127   let str = replace_str str "\t" "\\t" in
7128   let str = replace_str str "\000" "\\0" in
7129   str
7130
7131 (* Generate a lot of different functions for guestfish. *)
7132 and generate_fish_cmds () =
7133   generate_header CStyle GPLv2plus;
7134
7135   let all_functions =
7136     List.filter (
7137       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7138     ) all_functions in
7139   let all_functions_sorted =
7140     List.filter (
7141       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7142     ) all_functions_sorted in
7143
7144   pr "#include <config.h>\n";
7145   pr "\n";
7146   pr "#include <stdio.h>\n";
7147   pr "#include <stdlib.h>\n";
7148   pr "#include <string.h>\n";
7149   pr "#include <inttypes.h>\n";
7150   pr "\n";
7151   pr "#include <guestfs.h>\n";
7152   pr "#include \"c-ctype.h\"\n";
7153   pr "#include \"full-write.h\"\n";
7154   pr "#include \"xstrtol.h\"\n";
7155   pr "#include \"fish.h\"\n";
7156   pr "\n";
7157
7158   (* list_commands function, which implements guestfish -h *)
7159   pr "void list_commands (void)\n";
7160   pr "{\n";
7161   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7162   pr "  list_builtin_commands ();\n";
7163   List.iter (
7164     fun (name, _, _, flags, _, shortdesc, _) ->
7165       let name = replace_char name '_' '-' in
7166       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7167         name shortdesc
7168   ) all_functions_sorted;
7169   pr "  printf (\"    %%s\\n\",";
7170   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7171   pr "}\n";
7172   pr "\n";
7173
7174   (* display_command function, which implements guestfish -h cmd *)
7175   pr "void display_command (const char *cmd)\n";
7176   pr "{\n";
7177   List.iter (
7178     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7179       let name2 = replace_char name '_' '-' in
7180       let alias =
7181         try find_map (function FishAlias n -> Some n | _ -> None) flags
7182         with Not_found -> name in
7183       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7184       let synopsis =
7185         match snd style with
7186         | [] -> name2
7187         | args ->
7188             sprintf "%s %s"
7189               name2 (String.concat " " (List.map name_of_argt args)) in
7190
7191       let warnings =
7192         if List.mem ProtocolLimitWarning flags then
7193           ("\n\n" ^ protocol_limit_warning)
7194         else "" in
7195
7196       (* For DangerWillRobinson commands, we should probably have
7197        * guestfish prompt before allowing you to use them (especially
7198        * in interactive mode). XXX
7199        *)
7200       let warnings =
7201         warnings ^
7202           if List.mem DangerWillRobinson flags then
7203             ("\n\n" ^ danger_will_robinson)
7204           else "" in
7205
7206       let warnings =
7207         warnings ^
7208           match deprecation_notice flags with
7209           | None -> ""
7210           | Some txt -> "\n\n" ^ txt in
7211
7212       let describe_alias =
7213         if name <> alias then
7214           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7215         else "" in
7216
7217       pr "  if (";
7218       pr "STRCASEEQ (cmd, \"%s\")" name;
7219       if name <> name2 then
7220         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7221       if name <> alias then
7222         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7223       pr ")\n";
7224       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7225         name2 shortdesc
7226         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7227          "=head1 DESCRIPTION\n\n" ^
7228          longdesc ^ warnings ^ describe_alias);
7229       pr "  else\n"
7230   ) all_functions;
7231   pr "    display_builtin_command (cmd);\n";
7232   pr "}\n";
7233   pr "\n";
7234
7235   let emit_print_list_function typ =
7236     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7237       typ typ typ;
7238     pr "{\n";
7239     pr "  unsigned int i;\n";
7240     pr "\n";
7241     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7242     pr "    printf (\"[%%d] = {\\n\", i);\n";
7243     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7244     pr "    printf (\"}\\n\");\n";
7245     pr "  }\n";
7246     pr "}\n";
7247     pr "\n";
7248   in
7249
7250   (* print_* functions *)
7251   List.iter (
7252     fun (typ, cols) ->
7253       let needs_i =
7254         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7255
7256       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7257       pr "{\n";
7258       if needs_i then (
7259         pr "  unsigned int i;\n";
7260         pr "\n"
7261       );
7262       List.iter (
7263         function
7264         | name, FString ->
7265             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7266         | name, FUUID ->
7267             pr "  printf (\"%%s%s: \", indent);\n" name;
7268             pr "  for (i = 0; i < 32; ++i)\n";
7269             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7270             pr "  printf (\"\\n\");\n"
7271         | name, FBuffer ->
7272             pr "  printf (\"%%s%s: \", indent);\n" name;
7273             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7274             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7275             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7276             pr "    else\n";
7277             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7278             pr "  printf (\"\\n\");\n"
7279         | name, (FUInt64|FBytes) ->
7280             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7281               name typ name
7282         | name, FInt64 ->
7283             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7284               name typ name
7285         | name, FUInt32 ->
7286             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7287               name typ name
7288         | name, FInt32 ->
7289             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7290               name typ name
7291         | name, FChar ->
7292             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7293               name typ name
7294         | name, FOptPercent ->
7295             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7296               typ name name typ name;
7297             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7298       ) cols;
7299       pr "}\n";
7300       pr "\n";
7301   ) structs;
7302
7303   (* Emit a print_TYPE_list function definition only if that function is used. *)
7304   List.iter (
7305     function
7306     | typ, (RStructListOnly | RStructAndList) ->
7307         (* generate the function for typ *)
7308         emit_print_list_function typ
7309     | typ, _ -> () (* empty *)
7310   ) (rstructs_used_by all_functions);
7311
7312   (* Emit a print_TYPE function definition only if that function is used. *)
7313   List.iter (
7314     function
7315     | typ, (RStructOnly | RStructAndList) ->
7316         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7317         pr "{\n";
7318         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7319         pr "}\n";
7320         pr "\n";
7321     | typ, _ -> () (* empty *)
7322   ) (rstructs_used_by all_functions);
7323
7324   (* run_<action> actions *)
7325   List.iter (
7326     fun (name, style, _, flags, _, _, _) ->
7327       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7328       pr "{\n";
7329       (match fst style with
7330        | RErr
7331        | RInt _
7332        | RBool _ -> pr "  int r;\n"
7333        | RInt64 _ -> pr "  int64_t r;\n"
7334        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7335        | RString _ -> pr "  char *r;\n"
7336        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7337        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7338        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7339        | RBufferOut _ ->
7340            pr "  char *r;\n";
7341            pr "  size_t size;\n";
7342       );
7343       List.iter (
7344         function
7345         | Device n
7346         | String n
7347         | OptString n
7348         | FileIn n
7349         | FileOut n -> pr "  const char *%s;\n" n
7350         | Pathname n
7351         | Dev_or_Path n -> pr "  char *%s;\n" n
7352         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7353         | Bool n -> pr "  int %s;\n" n
7354         | Int n -> pr "  int %s;\n" n
7355         | Int64 n -> pr "  int64_t %s;\n" n
7356       ) (snd style);
7357
7358       (* Check and convert parameters. *)
7359       let argc_expected = List.length (snd style) in
7360       pr "  if (argc != %d) {\n" argc_expected;
7361       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7362         argc_expected;
7363       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7364       pr "    return -1;\n";
7365       pr "  }\n";
7366
7367       let parse_integer fn fntyp rtyp range name i =
7368         pr "  {\n";
7369         pr "    strtol_error xerr;\n";
7370         pr "    %s r;\n" fntyp;
7371         pr "\n";
7372         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7373         pr "    if (xerr != LONGINT_OK) {\n";
7374         pr "      fprintf (stderr,\n";
7375         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7376         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7377         pr "      return -1;\n";
7378         pr "    }\n";
7379         (match range with
7380          | None -> ()
7381          | Some (min, max, comment) ->
7382              pr "    /* %s */\n" comment;
7383              pr "    if (r < %s || r > %s) {\n" min max;
7384              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7385                name;
7386              pr "      return -1;\n";
7387              pr "    }\n";
7388              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7389         );
7390         pr "    %s = r;\n" name;
7391         pr "  }\n";
7392       in
7393
7394       iteri (
7395         fun i ->
7396           function
7397           | Device name
7398           | String name ->
7399               pr "  %s = argv[%d];\n" name i
7400           | Pathname name
7401           | Dev_or_Path name ->
7402               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7403               pr "  if (%s == NULL) return -1;\n" name
7404           | OptString name ->
7405               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7406                 name i i
7407           | FileIn name ->
7408               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7409                 name i i
7410           | FileOut name ->
7411               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7412                 name i i
7413           | StringList name | DeviceList name ->
7414               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7415               pr "  if (%s == NULL) return -1;\n" name;
7416           | Bool name ->
7417               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7418           | Int name ->
7419               let range =
7420                 let min = "(-(2LL<<30))"
7421                 and max = "((2LL<<30)-1)"
7422                 and comment =
7423                   "The Int type in the generator is a signed 31 bit int." in
7424                 Some (min, max, comment) in
7425               parse_integer "xstrtoll" "long long" "int" range name i
7426           | Int64 name ->
7427               parse_integer "xstrtoll" "long long" "int64_t" None name i
7428       ) (snd style);
7429
7430       (* Call C API function. *)
7431       let fn =
7432         try find_map (function FishAction n -> Some n | _ -> None) flags
7433         with Not_found -> sprintf "guestfs_%s" name in
7434       pr "  r = %s " fn;
7435       generate_c_call_args ~handle:"g" style;
7436       pr ";\n";
7437
7438       List.iter (
7439         function
7440         | Device name | String name
7441         | OptString name | FileIn name | FileOut name | Bool name
7442         | Int name | Int64 name -> ()
7443         | Pathname name | Dev_or_Path name ->
7444             pr "  free (%s);\n" name
7445         | StringList name | DeviceList name ->
7446             pr "  free_strings (%s);\n" name
7447       ) (snd style);
7448
7449       (* Check return value for errors and display command results. *)
7450       (match fst style with
7451        | RErr -> pr "  return r;\n"
7452        | RInt _ ->
7453            pr "  if (r == -1) return -1;\n";
7454            pr "  printf (\"%%d\\n\", r);\n";
7455            pr "  return 0;\n"
7456        | RInt64 _ ->
7457            pr "  if (r == -1) return -1;\n";
7458            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7459            pr "  return 0;\n"
7460        | RBool _ ->
7461            pr "  if (r == -1) return -1;\n";
7462            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7463            pr "  return 0;\n"
7464        | RConstString _ ->
7465            pr "  if (r == NULL) return -1;\n";
7466            pr "  printf (\"%%s\\n\", r);\n";
7467            pr "  return 0;\n"
7468        | RConstOptString _ ->
7469            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7470            pr "  return 0;\n"
7471        | RString _ ->
7472            pr "  if (r == NULL) return -1;\n";
7473            pr "  printf (\"%%s\\n\", r);\n";
7474            pr "  free (r);\n";
7475            pr "  return 0;\n"
7476        | RStringList _ ->
7477            pr "  if (r == NULL) return -1;\n";
7478            pr "  print_strings (r);\n";
7479            pr "  free_strings (r);\n";
7480            pr "  return 0;\n"
7481        | RStruct (_, typ) ->
7482            pr "  if (r == NULL) return -1;\n";
7483            pr "  print_%s (r);\n" typ;
7484            pr "  guestfs_free_%s (r);\n" typ;
7485            pr "  return 0;\n"
7486        | RStructList (_, typ) ->
7487            pr "  if (r == NULL) return -1;\n";
7488            pr "  print_%s_list (r);\n" typ;
7489            pr "  guestfs_free_%s_list (r);\n" typ;
7490            pr "  return 0;\n"
7491        | RHashtable _ ->
7492            pr "  if (r == NULL) return -1;\n";
7493            pr "  print_table (r);\n";
7494            pr "  free_strings (r);\n";
7495            pr "  return 0;\n"
7496        | RBufferOut _ ->
7497            pr "  if (r == NULL) return -1;\n";
7498            pr "  if (full_write (1, r, size) != size) {\n";
7499            pr "    perror (\"write\");\n";
7500            pr "    free (r);\n";
7501            pr "    return -1;\n";
7502            pr "  }\n";
7503            pr "  free (r);\n";
7504            pr "  return 0;\n"
7505       );
7506       pr "}\n";
7507       pr "\n"
7508   ) all_functions;
7509
7510   (* run_action function *)
7511   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7512   pr "{\n";
7513   List.iter (
7514     fun (name, _, _, flags, _, _, _) ->
7515       let name2 = replace_char name '_' '-' in
7516       let alias =
7517         try find_map (function FishAlias n -> Some n | _ -> None) flags
7518         with Not_found -> name in
7519       pr "  if (";
7520       pr "STRCASEEQ (cmd, \"%s\")" name;
7521       if name <> name2 then
7522         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7523       if name <> alias then
7524         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7525       pr ")\n";
7526       pr "    return run_%s (cmd, argc, argv);\n" name;
7527       pr "  else\n";
7528   ) all_functions;
7529   pr "    {\n";
7530   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7531   pr "      if (command_num == 1)\n";
7532   pr "        extended_help_message ();\n";
7533   pr "      return -1;\n";
7534   pr "    }\n";
7535   pr "  return 0;\n";
7536   pr "}\n";
7537   pr "\n"
7538
7539 (* Readline completion for guestfish. *)
7540 and generate_fish_completion () =
7541   generate_header CStyle GPLv2plus;
7542
7543   let all_functions =
7544     List.filter (
7545       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7546     ) all_functions in
7547
7548   pr "\
7549 #include <config.h>
7550
7551 #include <stdio.h>
7552 #include <stdlib.h>
7553 #include <string.h>
7554
7555 #ifdef HAVE_LIBREADLINE
7556 #include <readline/readline.h>
7557 #endif
7558
7559 #include \"fish.h\"
7560
7561 #ifdef HAVE_LIBREADLINE
7562
7563 static const char *const commands[] = {
7564   BUILTIN_COMMANDS_FOR_COMPLETION,
7565 ";
7566
7567   (* Get the commands, including the aliases.  They don't need to be
7568    * sorted - the generator() function just does a dumb linear search.
7569    *)
7570   let commands =
7571     List.map (
7572       fun (name, _, _, flags, _, _, _) ->
7573         let name2 = replace_char name '_' '-' in
7574         let alias =
7575           try find_map (function FishAlias n -> Some n | _ -> None) flags
7576           with Not_found -> name in
7577
7578         if name <> alias then [name2; alias] else [name2]
7579     ) all_functions in
7580   let commands = List.flatten commands in
7581
7582   List.iter (pr "  \"%s\",\n") commands;
7583
7584   pr "  NULL
7585 };
7586
7587 static char *
7588 generator (const char *text, int state)
7589 {
7590   static int index, len;
7591   const char *name;
7592
7593   if (!state) {
7594     index = 0;
7595     len = strlen (text);
7596   }
7597
7598   rl_attempted_completion_over = 1;
7599
7600   while ((name = commands[index]) != NULL) {
7601     index++;
7602     if (STRCASEEQLEN (name, text, len))
7603       return strdup (name);
7604   }
7605
7606   return NULL;
7607 }
7608
7609 #endif /* HAVE_LIBREADLINE */
7610
7611 #ifdef HAVE_RL_COMPLETION_MATCHES
7612 #define RL_COMPLETION_MATCHES rl_completion_matches
7613 #else
7614 #ifdef HAVE_COMPLETION_MATCHES
7615 #define RL_COMPLETION_MATCHES completion_matches
7616 #endif
7617 #endif /* else just fail if we don't have either symbol */
7618
7619 char **
7620 do_completion (const char *text, int start, int end)
7621 {
7622   char **matches = NULL;
7623
7624 #ifdef HAVE_LIBREADLINE
7625   rl_completion_append_character = ' ';
7626
7627   if (start == 0)
7628     matches = RL_COMPLETION_MATCHES (text, generator);
7629   else if (complete_dest_paths)
7630     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7631 #endif
7632
7633   return matches;
7634 }
7635 ";
7636
7637 (* Generate the POD documentation for guestfish. *)
7638 and generate_fish_actions_pod () =
7639   let all_functions_sorted =
7640     List.filter (
7641       fun (_, _, _, flags, _, _, _) ->
7642         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7643     ) all_functions_sorted in
7644
7645   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7646
7647   List.iter (
7648     fun (name, style, _, flags, _, _, longdesc) ->
7649       let longdesc =
7650         Str.global_substitute rex (
7651           fun s ->
7652             let sub =
7653               try Str.matched_group 1 s
7654               with Not_found ->
7655                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7656             "C<" ^ replace_char sub '_' '-' ^ ">"
7657         ) longdesc in
7658       let name = replace_char name '_' '-' in
7659       let alias =
7660         try find_map (function FishAlias n -> Some n | _ -> None) flags
7661         with Not_found -> name in
7662
7663       pr "=head2 %s" name;
7664       if name <> alias then
7665         pr " | %s" alias;
7666       pr "\n";
7667       pr "\n";
7668       pr " %s" name;
7669       List.iter (
7670         function
7671         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7672         | OptString n -> pr " %s" n
7673         | StringList n | DeviceList n -> pr " '%s ...'" n
7674         | Bool _ -> pr " true|false"
7675         | Int n -> pr " %s" n
7676         | Int64 n -> pr " %s" n
7677         | FileIn n | FileOut n -> pr " (%s|-)" n
7678       ) (snd style);
7679       pr "\n";
7680       pr "\n";
7681       pr "%s\n\n" longdesc;
7682
7683       if List.exists (function FileIn _ | FileOut _ -> true
7684                       | _ -> false) (snd style) then
7685         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7686
7687       if List.mem ProtocolLimitWarning flags then
7688         pr "%s\n\n" protocol_limit_warning;
7689
7690       if List.mem DangerWillRobinson flags then
7691         pr "%s\n\n" danger_will_robinson;
7692
7693       match deprecation_notice flags with
7694       | None -> ()
7695       | Some txt -> pr "%s\n\n" txt
7696   ) all_functions_sorted
7697
7698 (* Generate a C function prototype. *)
7699 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7700     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7701     ?(prefix = "")
7702     ?handle name style =
7703   if extern then pr "extern ";
7704   if static then pr "static ";
7705   (match fst style with
7706    | RErr -> pr "int "
7707    | RInt _ -> pr "int "
7708    | RInt64 _ -> pr "int64_t "
7709    | RBool _ -> pr "int "
7710    | RConstString _ | RConstOptString _ -> pr "const char *"
7711    | RString _ | RBufferOut _ -> pr "char *"
7712    | RStringList _ | RHashtable _ -> pr "char **"
7713    | RStruct (_, typ) ->
7714        if not in_daemon then pr "struct guestfs_%s *" typ
7715        else pr "guestfs_int_%s *" typ
7716    | RStructList (_, typ) ->
7717        if not in_daemon then pr "struct guestfs_%s_list *" typ
7718        else pr "guestfs_int_%s_list *" typ
7719   );
7720   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7721   pr "%s%s (" prefix name;
7722   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7723     pr "void"
7724   else (
7725     let comma = ref false in
7726     (match handle with
7727      | None -> ()
7728      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7729     );
7730     let next () =
7731       if !comma then (
7732         if single_line then pr ", " else pr ",\n\t\t"
7733       );
7734       comma := true
7735     in
7736     List.iter (
7737       function
7738       | Pathname n
7739       | Device n | Dev_or_Path n
7740       | String n
7741       | OptString n ->
7742           next ();
7743           pr "const char *%s" n
7744       | StringList n | DeviceList n ->
7745           next ();
7746           pr "char *const *%s" n
7747       | Bool n -> next (); pr "int %s" n
7748       | Int n -> next (); pr "int %s" n
7749       | Int64 n -> next (); pr "int64_t %s" n
7750       | FileIn n
7751       | FileOut n ->
7752           if not in_daemon then (next (); pr "const char *%s" n)
7753     ) (snd style);
7754     if is_RBufferOut then (next (); pr "size_t *size_r");
7755   );
7756   pr ")";
7757   if semicolon then pr ";";
7758   if newline then pr "\n"
7759
7760 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7761 and generate_c_call_args ?handle ?(decl = false) style =
7762   pr "(";
7763   let comma = ref false in
7764   let next () =
7765     if !comma then pr ", ";
7766     comma := true
7767   in
7768   (match handle with
7769    | None -> ()
7770    | Some handle -> pr "%s" handle; comma := true
7771   );
7772   List.iter (
7773     fun arg ->
7774       next ();
7775       pr "%s" (name_of_argt arg)
7776   ) (snd style);
7777   (* For RBufferOut calls, add implicit &size parameter. *)
7778   if not decl then (
7779     match fst style with
7780     | RBufferOut _ ->
7781         next ();
7782         pr "&size"
7783     | _ -> ()
7784   );
7785   pr ")"
7786
7787 (* Generate the OCaml bindings interface. *)
7788 and generate_ocaml_mli () =
7789   generate_header OCamlStyle LGPLv2plus;
7790
7791   pr "\
7792 (** For API documentation you should refer to the C API
7793     in the guestfs(3) manual page.  The OCaml API uses almost
7794     exactly the same calls. *)
7795
7796 type t
7797 (** A [guestfs_h] handle. *)
7798
7799 exception Error of string
7800 (** This exception is raised when there is an error. *)
7801
7802 exception Handle_closed of string
7803 (** This exception is raised if you use a {!Guestfs.t} handle
7804     after calling {!close} on it.  The string is the name of
7805     the function. *)
7806
7807 val create : unit -> t
7808 (** Create a {!Guestfs.t} handle. *)
7809
7810 val close : t -> unit
7811 (** Close the {!Guestfs.t} handle and free up all resources used
7812     by it immediately.
7813
7814     Handles are closed by the garbage collector when they become
7815     unreferenced, but callers can call this in order to provide
7816     predictable cleanup. *)
7817
7818 ";
7819   generate_ocaml_structure_decls ();
7820
7821   (* The actions. *)
7822   List.iter (
7823     fun (name, style, _, _, _, shortdesc, _) ->
7824       generate_ocaml_prototype name style;
7825       pr "(** %s *)\n" shortdesc;
7826       pr "\n"
7827   ) all_functions_sorted
7828
7829 (* Generate the OCaml bindings implementation. *)
7830 and generate_ocaml_ml () =
7831   generate_header OCamlStyle LGPLv2plus;
7832
7833   pr "\
7834 type t
7835
7836 exception Error of string
7837 exception Handle_closed of string
7838
7839 external create : unit -> t = \"ocaml_guestfs_create\"
7840 external close : t -> unit = \"ocaml_guestfs_close\"
7841
7842 (* Give the exceptions names, so they can be raised from the C code. *)
7843 let () =
7844   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7845   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7846
7847 ";
7848
7849   generate_ocaml_structure_decls ();
7850
7851   (* The actions. *)
7852   List.iter (
7853     fun (name, style, _, _, _, shortdesc, _) ->
7854       generate_ocaml_prototype ~is_external:true name style;
7855   ) all_functions_sorted
7856
7857 (* Generate the OCaml bindings C implementation. *)
7858 and generate_ocaml_c () =
7859   generate_header CStyle LGPLv2plus;
7860
7861   pr "\
7862 #include <stdio.h>
7863 #include <stdlib.h>
7864 #include <string.h>
7865
7866 #include <caml/config.h>
7867 #include <caml/alloc.h>
7868 #include <caml/callback.h>
7869 #include <caml/fail.h>
7870 #include <caml/memory.h>
7871 #include <caml/mlvalues.h>
7872 #include <caml/signals.h>
7873
7874 #include <guestfs.h>
7875
7876 #include \"guestfs_c.h\"
7877
7878 /* Copy a hashtable of string pairs into an assoc-list.  We return
7879  * the list in reverse order, but hashtables aren't supposed to be
7880  * ordered anyway.
7881  */
7882 static CAMLprim value
7883 copy_table (char * const * argv)
7884 {
7885   CAMLparam0 ();
7886   CAMLlocal5 (rv, pairv, kv, vv, cons);
7887   int i;
7888
7889   rv = Val_int (0);
7890   for (i = 0; argv[i] != NULL; i += 2) {
7891     kv = caml_copy_string (argv[i]);
7892     vv = caml_copy_string (argv[i+1]);
7893     pairv = caml_alloc (2, 0);
7894     Store_field (pairv, 0, kv);
7895     Store_field (pairv, 1, vv);
7896     cons = caml_alloc (2, 0);
7897     Store_field (cons, 1, rv);
7898     rv = cons;
7899     Store_field (cons, 0, pairv);
7900   }
7901
7902   CAMLreturn (rv);
7903 }
7904
7905 ";
7906
7907   (* Struct copy functions. *)
7908
7909   let emit_ocaml_copy_list_function typ =
7910     pr "static CAMLprim value\n";
7911     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7912     pr "{\n";
7913     pr "  CAMLparam0 ();\n";
7914     pr "  CAMLlocal2 (rv, v);\n";
7915     pr "  unsigned int i;\n";
7916     pr "\n";
7917     pr "  if (%ss->len == 0)\n" typ;
7918     pr "    CAMLreturn (Atom (0));\n";
7919     pr "  else {\n";
7920     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7921     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7922     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7923     pr "      caml_modify (&Field (rv, i), v);\n";
7924     pr "    }\n";
7925     pr "    CAMLreturn (rv);\n";
7926     pr "  }\n";
7927     pr "}\n";
7928     pr "\n";
7929   in
7930
7931   List.iter (
7932     fun (typ, cols) ->
7933       let has_optpercent_col =
7934         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7935
7936       pr "static CAMLprim value\n";
7937       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7938       pr "{\n";
7939       pr "  CAMLparam0 ();\n";
7940       if has_optpercent_col then
7941         pr "  CAMLlocal3 (rv, v, v2);\n"
7942       else
7943         pr "  CAMLlocal2 (rv, v);\n";
7944       pr "\n";
7945       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7946       iteri (
7947         fun i col ->
7948           (match col with
7949            | name, FString ->
7950                pr "  v = caml_copy_string (%s->%s);\n" typ name
7951            | name, FBuffer ->
7952                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7953                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7954                  typ name typ name
7955            | name, FUUID ->
7956                pr "  v = caml_alloc_string (32);\n";
7957                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7958            | name, (FBytes|FInt64|FUInt64) ->
7959                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7960            | name, (FInt32|FUInt32) ->
7961                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7962            | name, FOptPercent ->
7963                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7964                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7965                pr "    v = caml_alloc (1, 0);\n";
7966                pr "    Store_field (v, 0, v2);\n";
7967                pr "  } else /* None */\n";
7968                pr "    v = Val_int (0);\n";
7969            | name, FChar ->
7970                pr "  v = Val_int (%s->%s);\n" typ name
7971           );
7972           pr "  Store_field (rv, %d, v);\n" i
7973       ) cols;
7974       pr "  CAMLreturn (rv);\n";
7975       pr "}\n";
7976       pr "\n";
7977   ) structs;
7978
7979   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7980   List.iter (
7981     function
7982     | typ, (RStructListOnly | RStructAndList) ->
7983         (* generate the function for typ *)
7984         emit_ocaml_copy_list_function typ
7985     | typ, _ -> () (* empty *)
7986   ) (rstructs_used_by all_functions);
7987
7988   (* The wrappers. *)
7989   List.iter (
7990     fun (name, style, _, _, _, _, _) ->
7991       pr "/* Automatically generated wrapper for function\n";
7992       pr " * ";
7993       generate_ocaml_prototype name style;
7994       pr " */\n";
7995       pr "\n";
7996
7997       let params =
7998         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7999
8000       let needs_extra_vs =
8001         match fst style with RConstOptString _ -> true | _ -> false in
8002
8003       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8004       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8005       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8006       pr "\n";
8007
8008       pr "CAMLprim value\n";
8009       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8010       List.iter (pr ", value %s") (List.tl params);
8011       pr ")\n";
8012       pr "{\n";
8013
8014       (match params with
8015        | [p1; p2; p3; p4; p5] ->
8016            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8017        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8018            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8019            pr "  CAMLxparam%d (%s);\n"
8020              (List.length rest) (String.concat ", " rest)
8021        | ps ->
8022            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8023       );
8024       if not needs_extra_vs then
8025         pr "  CAMLlocal1 (rv);\n"
8026       else
8027         pr "  CAMLlocal3 (rv, v, v2);\n";
8028       pr "\n";
8029
8030       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8031       pr "  if (g == NULL)\n";
8032       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8033       pr "\n";
8034
8035       List.iter (
8036         function
8037         | Pathname n
8038         | Device n | Dev_or_Path n
8039         | String n
8040         | FileIn n
8041         | FileOut n ->
8042             pr "  const char *%s = String_val (%sv);\n" n n
8043         | OptString n ->
8044             pr "  const char *%s =\n" n;
8045             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8046               n n
8047         | StringList n | DeviceList n ->
8048             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8049         | Bool n ->
8050             pr "  int %s = Bool_val (%sv);\n" n n
8051         | Int n ->
8052             pr "  int %s = Int_val (%sv);\n" n n
8053         | Int64 n ->
8054             pr "  int64_t %s = Int64_val (%sv);\n" n n
8055       ) (snd style);
8056       let error_code =
8057         match fst style with
8058         | RErr -> pr "  int r;\n"; "-1"
8059         | RInt _ -> pr "  int r;\n"; "-1"
8060         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8061         | RBool _ -> pr "  int r;\n"; "-1"
8062         | RConstString _ | RConstOptString _ ->
8063             pr "  const char *r;\n"; "NULL"
8064         | RString _ -> pr "  char *r;\n"; "NULL"
8065         | RStringList _ ->
8066             pr "  int i;\n";
8067             pr "  char **r;\n";
8068             "NULL"
8069         | RStruct (_, typ) ->
8070             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8071         | RStructList (_, typ) ->
8072             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8073         | RHashtable _ ->
8074             pr "  int i;\n";
8075             pr "  char **r;\n";
8076             "NULL"
8077         | RBufferOut _ ->
8078             pr "  char *r;\n";
8079             pr "  size_t size;\n";
8080             "NULL" in
8081       pr "\n";
8082
8083       pr "  caml_enter_blocking_section ();\n";
8084       pr "  r = guestfs_%s " name;
8085       generate_c_call_args ~handle:"g" style;
8086       pr ";\n";
8087       pr "  caml_leave_blocking_section ();\n";
8088
8089       List.iter (
8090         function
8091         | StringList n | DeviceList n ->
8092             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8093         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8094         | Bool _ | Int _ | Int64 _
8095         | FileIn _ | FileOut _ -> ()
8096       ) (snd style);
8097
8098       pr "  if (r == %s)\n" error_code;
8099       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8100       pr "\n";
8101
8102       (match fst style with
8103        | RErr -> pr "  rv = Val_unit;\n"
8104        | RInt _ -> pr "  rv = Val_int (r);\n"
8105        | RInt64 _ ->
8106            pr "  rv = caml_copy_int64 (r);\n"
8107        | RBool _ -> pr "  rv = Val_bool (r);\n"
8108        | RConstString _ ->
8109            pr "  rv = caml_copy_string (r);\n"
8110        | RConstOptString _ ->
8111            pr "  if (r) { /* Some string */\n";
8112            pr "    v = caml_alloc (1, 0);\n";
8113            pr "    v2 = caml_copy_string (r);\n";
8114            pr "    Store_field (v, 0, v2);\n";
8115            pr "  } else /* None */\n";
8116            pr "    v = Val_int (0);\n";
8117        | RString _ ->
8118            pr "  rv = caml_copy_string (r);\n";
8119            pr "  free (r);\n"
8120        | RStringList _ ->
8121            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8122            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8123            pr "  free (r);\n"
8124        | RStruct (_, typ) ->
8125            pr "  rv = copy_%s (r);\n" typ;
8126            pr "  guestfs_free_%s (r);\n" typ;
8127        | RStructList (_, typ) ->
8128            pr "  rv = copy_%s_list (r);\n" typ;
8129            pr "  guestfs_free_%s_list (r);\n" typ;
8130        | RHashtable _ ->
8131            pr "  rv = copy_table (r);\n";
8132            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8133            pr "  free (r);\n";
8134        | RBufferOut _ ->
8135            pr "  rv = caml_alloc_string (size);\n";
8136            pr "  memcpy (String_val (rv), r, size);\n";
8137       );
8138
8139       pr "  CAMLreturn (rv);\n";
8140       pr "}\n";
8141       pr "\n";
8142
8143       if List.length params > 5 then (
8144         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8145         pr "CAMLprim value ";
8146         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8147         pr "CAMLprim value\n";
8148         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8149         pr "{\n";
8150         pr "  return ocaml_guestfs_%s (argv[0]" name;
8151         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8152         pr ");\n";
8153         pr "}\n";
8154         pr "\n"
8155       )
8156   ) all_functions_sorted
8157
8158 and generate_ocaml_structure_decls () =
8159   List.iter (
8160     fun (typ, cols) ->
8161       pr "type %s = {\n" typ;
8162       List.iter (
8163         function
8164         | name, FString -> pr "  %s : string;\n" name
8165         | name, FBuffer -> pr "  %s : string;\n" name
8166         | name, FUUID -> pr "  %s : string;\n" name
8167         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8168         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8169         | name, FChar -> pr "  %s : char;\n" name
8170         | name, FOptPercent -> pr "  %s : float option;\n" name
8171       ) cols;
8172       pr "}\n";
8173       pr "\n"
8174   ) structs
8175
8176 and generate_ocaml_prototype ?(is_external = false) name style =
8177   if is_external then pr "external " else pr "val ";
8178   pr "%s : t -> " name;
8179   List.iter (
8180     function
8181     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8182     | OptString _ -> pr "string option -> "
8183     | StringList _ | DeviceList _ -> pr "string array -> "
8184     | Bool _ -> pr "bool -> "
8185     | Int _ -> pr "int -> "
8186     | Int64 _ -> pr "int64 -> "
8187   ) (snd style);
8188   (match fst style with
8189    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8190    | RInt _ -> pr "int"
8191    | RInt64 _ -> pr "int64"
8192    | RBool _ -> pr "bool"
8193    | RConstString _ -> pr "string"
8194    | RConstOptString _ -> pr "string option"
8195    | RString _ | RBufferOut _ -> pr "string"
8196    | RStringList _ -> pr "string array"
8197    | RStruct (_, typ) -> pr "%s" typ
8198    | RStructList (_, typ) -> pr "%s array" typ
8199    | RHashtable _ -> pr "(string * string) list"
8200   );
8201   if is_external then (
8202     pr " = ";
8203     if List.length (snd style) + 1 > 5 then
8204       pr "\"ocaml_guestfs_%s_byte\" " name;
8205     pr "\"ocaml_guestfs_%s\"" name
8206   );
8207   pr "\n"
8208
8209 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8210 and generate_perl_xs () =
8211   generate_header CStyle LGPLv2plus;
8212
8213   pr "\
8214 #include \"EXTERN.h\"
8215 #include \"perl.h\"
8216 #include \"XSUB.h\"
8217
8218 #include <guestfs.h>
8219
8220 #ifndef PRId64
8221 #define PRId64 \"lld\"
8222 #endif
8223
8224 static SV *
8225 my_newSVll(long long val) {
8226 #ifdef USE_64_BIT_ALL
8227   return newSViv(val);
8228 #else
8229   char buf[100];
8230   int len;
8231   len = snprintf(buf, 100, \"%%\" PRId64, val);
8232   return newSVpv(buf, len);
8233 #endif
8234 }
8235
8236 #ifndef PRIu64
8237 #define PRIu64 \"llu\"
8238 #endif
8239
8240 static SV *
8241 my_newSVull(unsigned long long val) {
8242 #ifdef USE_64_BIT_ALL
8243   return newSVuv(val);
8244 #else
8245   char buf[100];
8246   int len;
8247   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8248   return newSVpv(buf, len);
8249 #endif
8250 }
8251
8252 /* http://www.perlmonks.org/?node_id=680842 */
8253 static char **
8254 XS_unpack_charPtrPtr (SV *arg) {
8255   char **ret;
8256   AV *av;
8257   I32 i;
8258
8259   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8260     croak (\"array reference expected\");
8261
8262   av = (AV *)SvRV (arg);
8263   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8264   if (!ret)
8265     croak (\"malloc failed\");
8266
8267   for (i = 0; i <= av_len (av); i++) {
8268     SV **elem = av_fetch (av, i, 0);
8269
8270     if (!elem || !*elem)
8271       croak (\"missing element in list\");
8272
8273     ret[i] = SvPV_nolen (*elem);
8274   }
8275
8276   ret[i] = NULL;
8277
8278   return ret;
8279 }
8280
8281 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8282
8283 PROTOTYPES: ENABLE
8284
8285 guestfs_h *
8286 _create ()
8287    CODE:
8288       RETVAL = guestfs_create ();
8289       if (!RETVAL)
8290         croak (\"could not create guestfs handle\");
8291       guestfs_set_error_handler (RETVAL, NULL, NULL);
8292  OUTPUT:
8293       RETVAL
8294
8295 void
8296 DESTROY (g)
8297       guestfs_h *g;
8298  PPCODE:
8299       guestfs_close (g);
8300
8301 ";
8302
8303   List.iter (
8304     fun (name, style, _, _, _, _, _) ->
8305       (match fst style with
8306        | RErr -> pr "void\n"
8307        | RInt _ -> pr "SV *\n"
8308        | RInt64 _ -> pr "SV *\n"
8309        | RBool _ -> pr "SV *\n"
8310        | RConstString _ -> pr "SV *\n"
8311        | RConstOptString _ -> pr "SV *\n"
8312        | RString _ -> pr "SV *\n"
8313        | RBufferOut _ -> pr "SV *\n"
8314        | RStringList _
8315        | RStruct _ | RStructList _
8316        | RHashtable _ ->
8317            pr "void\n" (* all lists returned implictly on the stack *)
8318       );
8319       (* Call and arguments. *)
8320       pr "%s " name;
8321       generate_c_call_args ~handle:"g" ~decl:true style;
8322       pr "\n";
8323       pr "      guestfs_h *g;\n";
8324       iteri (
8325         fun i ->
8326           function
8327           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8328               pr "      char *%s;\n" n
8329           | OptString n ->
8330               (* http://www.perlmonks.org/?node_id=554277
8331                * Note that the implicit handle argument means we have
8332                * to add 1 to the ST(x) operator.
8333                *)
8334               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8335           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8336           | Bool n -> pr "      int %s;\n" n
8337           | Int n -> pr "      int %s;\n" n
8338           | Int64 n -> pr "      int64_t %s;\n" n
8339       ) (snd style);
8340
8341       let do_cleanups () =
8342         List.iter (
8343           function
8344           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8345           | Bool _ | Int _ | Int64 _
8346           | FileIn _ | FileOut _ -> ()
8347           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8348         ) (snd style)
8349       in
8350
8351       (* Code. *)
8352       (match fst style with
8353        | RErr ->
8354            pr "PREINIT:\n";
8355            pr "      int r;\n";
8356            pr " PPCODE:\n";
8357            pr "      r = guestfs_%s " name;
8358            generate_c_call_args ~handle:"g" style;
8359            pr ";\n";
8360            do_cleanups ();
8361            pr "      if (r == -1)\n";
8362            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8363        | RInt n
8364        | RBool n ->
8365            pr "PREINIT:\n";
8366            pr "      int %s;\n" n;
8367            pr "   CODE:\n";
8368            pr "      %s = guestfs_%s " n name;
8369            generate_c_call_args ~handle:"g" style;
8370            pr ";\n";
8371            do_cleanups ();
8372            pr "      if (%s == -1)\n" n;
8373            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8374            pr "      RETVAL = newSViv (%s);\n" n;
8375            pr " OUTPUT:\n";
8376            pr "      RETVAL\n"
8377        | RInt64 n ->
8378            pr "PREINIT:\n";
8379            pr "      int64_t %s;\n" n;
8380            pr "   CODE:\n";
8381            pr "      %s = guestfs_%s " n name;
8382            generate_c_call_args ~handle:"g" style;
8383            pr ";\n";
8384            do_cleanups ();
8385            pr "      if (%s == -1)\n" n;
8386            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8387            pr "      RETVAL = my_newSVll (%s);\n" n;
8388            pr " OUTPUT:\n";
8389            pr "      RETVAL\n"
8390        | RConstString n ->
8391            pr "PREINIT:\n";
8392            pr "      const char *%s;\n" n;
8393            pr "   CODE:\n";
8394            pr "      %s = guestfs_%s " n name;
8395            generate_c_call_args ~handle:"g" style;
8396            pr ";\n";
8397            do_cleanups ();
8398            pr "      if (%s == NULL)\n" n;
8399            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8400            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8401            pr " OUTPUT:\n";
8402            pr "      RETVAL\n"
8403        | RConstOptString n ->
8404            pr "PREINIT:\n";
8405            pr "      const char *%s;\n" n;
8406            pr "   CODE:\n";
8407            pr "      %s = guestfs_%s " n name;
8408            generate_c_call_args ~handle:"g" style;
8409            pr ";\n";
8410            do_cleanups ();
8411            pr "      if (%s == NULL)\n" n;
8412            pr "        RETVAL = &PL_sv_undef;\n";
8413            pr "      else\n";
8414            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8415            pr " OUTPUT:\n";
8416            pr "      RETVAL\n"
8417        | RString n ->
8418            pr "PREINIT:\n";
8419            pr "      char *%s;\n" n;
8420            pr "   CODE:\n";
8421            pr "      %s = guestfs_%s " n name;
8422            generate_c_call_args ~handle:"g" style;
8423            pr ";\n";
8424            do_cleanups ();
8425            pr "      if (%s == NULL)\n" n;
8426            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8427            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8428            pr "      free (%s);\n" n;
8429            pr " OUTPUT:\n";
8430            pr "      RETVAL\n"
8431        | RStringList n | RHashtable n ->
8432            pr "PREINIT:\n";
8433            pr "      char **%s;\n" n;
8434            pr "      int i, n;\n";
8435            pr " PPCODE:\n";
8436            pr "      %s = guestfs_%s " n name;
8437            generate_c_call_args ~handle:"g" style;
8438            pr ";\n";
8439            do_cleanups ();
8440            pr "      if (%s == NULL)\n" n;
8441            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8442            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8443            pr "      EXTEND (SP, n);\n";
8444            pr "      for (i = 0; i < n; ++i) {\n";
8445            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8446            pr "        free (%s[i]);\n" n;
8447            pr "      }\n";
8448            pr "      free (%s);\n" n;
8449        | RStruct (n, typ) ->
8450            let cols = cols_of_struct typ in
8451            generate_perl_struct_code typ cols name style n do_cleanups
8452        | RStructList (n, typ) ->
8453            let cols = cols_of_struct typ in
8454            generate_perl_struct_list_code typ cols name style n do_cleanups
8455        | RBufferOut n ->
8456            pr "PREINIT:\n";
8457            pr "      char *%s;\n" n;
8458            pr "      size_t size;\n";
8459            pr "   CODE:\n";
8460            pr "      %s = guestfs_%s " n name;
8461            generate_c_call_args ~handle:"g" style;
8462            pr ";\n";
8463            do_cleanups ();
8464            pr "      if (%s == NULL)\n" n;
8465            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8466            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8467            pr "      free (%s);\n" n;
8468            pr " OUTPUT:\n";
8469            pr "      RETVAL\n"
8470       );
8471
8472       pr "\n"
8473   ) all_functions
8474
8475 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8476   pr "PREINIT:\n";
8477   pr "      struct guestfs_%s_list *%s;\n" typ n;
8478   pr "      int i;\n";
8479   pr "      HV *hv;\n";
8480   pr " PPCODE:\n";
8481   pr "      %s = guestfs_%s " n name;
8482   generate_c_call_args ~handle:"g" style;
8483   pr ";\n";
8484   do_cleanups ();
8485   pr "      if (%s == NULL)\n" n;
8486   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8487   pr "      EXTEND (SP, %s->len);\n" n;
8488   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8489   pr "        hv = newHV ();\n";
8490   List.iter (
8491     function
8492     | name, FString ->
8493         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8494           name (String.length name) n name
8495     | name, FUUID ->
8496         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8497           name (String.length name) n name
8498     | name, FBuffer ->
8499         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8500           name (String.length name) n name n name
8501     | name, (FBytes|FUInt64) ->
8502         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8503           name (String.length name) n name
8504     | name, FInt64 ->
8505         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8506           name (String.length name) n name
8507     | name, (FInt32|FUInt32) ->
8508         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8509           name (String.length name) n name
8510     | name, FChar ->
8511         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8512           name (String.length name) n name
8513     | name, FOptPercent ->
8514         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8515           name (String.length name) n name
8516   ) cols;
8517   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8518   pr "      }\n";
8519   pr "      guestfs_free_%s_list (%s);\n" typ n
8520
8521 and generate_perl_struct_code typ cols name style n do_cleanups =
8522   pr "PREINIT:\n";
8523   pr "      struct guestfs_%s *%s;\n" typ n;
8524   pr " PPCODE:\n";
8525   pr "      %s = guestfs_%s " n name;
8526   generate_c_call_args ~handle:"g" style;
8527   pr ";\n";
8528   do_cleanups ();
8529   pr "      if (%s == NULL)\n" n;
8530   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8531   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8532   List.iter (
8533     fun ((name, _) as col) ->
8534       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8535
8536       match col with
8537       | name, FString ->
8538           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8539             n name
8540       | name, FBuffer ->
8541           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8542             n name n name
8543       | name, FUUID ->
8544           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8545             n name
8546       | name, (FBytes|FUInt64) ->
8547           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8548             n name
8549       | name, FInt64 ->
8550           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8551             n name
8552       | name, (FInt32|FUInt32) ->
8553           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8554             n name
8555       | name, FChar ->
8556           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8557             n name
8558       | name, FOptPercent ->
8559           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8560             n name
8561   ) cols;
8562   pr "      free (%s);\n" n
8563
8564 (* Generate Sys/Guestfs.pm. *)
8565 and generate_perl_pm () =
8566   generate_header HashStyle LGPLv2plus;
8567
8568   pr "\
8569 =pod
8570
8571 =head1 NAME
8572
8573 Sys::Guestfs - Perl bindings for libguestfs
8574
8575 =head1 SYNOPSIS
8576
8577  use Sys::Guestfs;
8578
8579  my $h = Sys::Guestfs->new ();
8580  $h->add_drive ('guest.img');
8581  $h->launch ();
8582  $h->mount ('/dev/sda1', '/');
8583  $h->touch ('/hello');
8584  $h->sync ();
8585
8586 =head1 DESCRIPTION
8587
8588 The C<Sys::Guestfs> module provides a Perl XS binding to the
8589 libguestfs API for examining and modifying virtual machine
8590 disk images.
8591
8592 Amongst the things this is good for: making batch configuration
8593 changes to guests, getting disk used/free statistics (see also:
8594 virt-df), migrating between virtualization systems (see also:
8595 virt-p2v), performing partial backups, performing partial guest
8596 clones, cloning guests and changing registry/UUID/hostname info, and
8597 much else besides.
8598
8599 Libguestfs uses Linux kernel and qemu code, and can access any type of
8600 guest filesystem that Linux and qemu can, including but not limited
8601 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8602 schemes, qcow, qcow2, vmdk.
8603
8604 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8605 LVs, what filesystem is in each LV, etc.).  It can also run commands
8606 in the context of the guest.  Also you can access filesystems over
8607 FUSE.
8608
8609 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8610 functions for using libguestfs from Perl, including integration
8611 with libvirt.
8612
8613 =head1 ERRORS
8614
8615 All errors turn into calls to C<croak> (see L<Carp(3)>).
8616
8617 =head1 METHODS
8618
8619 =over 4
8620
8621 =cut
8622
8623 package Sys::Guestfs;
8624
8625 use strict;
8626 use warnings;
8627
8628 require XSLoader;
8629 XSLoader::load ('Sys::Guestfs');
8630
8631 =item $h = Sys::Guestfs->new ();
8632
8633 Create a new guestfs handle.
8634
8635 =cut
8636
8637 sub new {
8638   my $proto = shift;
8639   my $class = ref ($proto) || $proto;
8640
8641   my $self = Sys::Guestfs::_create ();
8642   bless $self, $class;
8643   return $self;
8644 }
8645
8646 ";
8647
8648   (* Actions.  We only need to print documentation for these as
8649    * they are pulled in from the XS code automatically.
8650    *)
8651   List.iter (
8652     fun (name, style, _, flags, _, _, longdesc) ->
8653       if not (List.mem NotInDocs flags) then (
8654         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8655         pr "=item ";
8656         generate_perl_prototype name style;
8657         pr "\n\n";
8658         pr "%s\n\n" longdesc;
8659         if List.mem ProtocolLimitWarning flags then
8660           pr "%s\n\n" protocol_limit_warning;
8661         if List.mem DangerWillRobinson flags then
8662           pr "%s\n\n" danger_will_robinson;
8663         match deprecation_notice flags with
8664         | None -> ()
8665         | Some txt -> pr "%s\n\n" txt
8666       )
8667   ) all_functions_sorted;
8668
8669   (* End of file. *)
8670   pr "\
8671 =cut
8672
8673 1;
8674
8675 =back
8676
8677 =head1 COPYRIGHT
8678
8679 Copyright (C) %s Red Hat Inc.
8680
8681 =head1 LICENSE
8682
8683 Please see the file COPYING.LIB for the full license.
8684
8685 =head1 SEE ALSO
8686
8687 L<guestfs(3)>,
8688 L<guestfish(1)>,
8689 L<http://libguestfs.org>,
8690 L<Sys::Guestfs::Lib(3)>.
8691
8692 =cut
8693 " copyright_years
8694
8695 and generate_perl_prototype name style =
8696   (match fst style with
8697    | RErr -> ()
8698    | RBool n
8699    | RInt n
8700    | RInt64 n
8701    | RConstString n
8702    | RConstOptString n
8703    | RString n
8704    | RBufferOut n -> pr "$%s = " n
8705    | RStruct (n,_)
8706    | RHashtable n -> pr "%%%s = " n
8707    | RStringList n
8708    | RStructList (n,_) -> pr "@%s = " n
8709   );
8710   pr "$h->%s (" name;
8711   let comma = ref false in
8712   List.iter (
8713     fun arg ->
8714       if !comma then pr ", ";
8715       comma := true;
8716       match arg with
8717       | Pathname n | Device n | Dev_or_Path n | String n
8718       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8719           pr "$%s" n
8720       | StringList n | DeviceList n ->
8721           pr "\\@%s" n
8722   ) (snd style);
8723   pr ");"
8724
8725 (* Generate Python C module. *)
8726 and generate_python_c () =
8727   generate_header CStyle LGPLv2plus;
8728
8729   pr "\
8730 #include <Python.h>
8731
8732 #include <stdio.h>
8733 #include <stdlib.h>
8734 #include <assert.h>
8735
8736 #include \"guestfs.h\"
8737
8738 typedef struct {
8739   PyObject_HEAD
8740   guestfs_h *g;
8741 } Pyguestfs_Object;
8742
8743 static guestfs_h *
8744 get_handle (PyObject *obj)
8745 {
8746   assert (obj);
8747   assert (obj != Py_None);
8748   return ((Pyguestfs_Object *) obj)->g;
8749 }
8750
8751 static PyObject *
8752 put_handle (guestfs_h *g)
8753 {
8754   assert (g);
8755   return
8756     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8757 }
8758
8759 /* This list should be freed (but not the strings) after use. */
8760 static char **
8761 get_string_list (PyObject *obj)
8762 {
8763   int i, len;
8764   char **r;
8765
8766   assert (obj);
8767
8768   if (!PyList_Check (obj)) {
8769     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8770     return NULL;
8771   }
8772
8773   len = PyList_Size (obj);
8774   r = malloc (sizeof (char *) * (len+1));
8775   if (r == NULL) {
8776     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8777     return NULL;
8778   }
8779
8780   for (i = 0; i < len; ++i)
8781     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8782   r[len] = NULL;
8783
8784   return r;
8785 }
8786
8787 static PyObject *
8788 put_string_list (char * const * const argv)
8789 {
8790   PyObject *list;
8791   int argc, i;
8792
8793   for (argc = 0; argv[argc] != NULL; ++argc)
8794     ;
8795
8796   list = PyList_New (argc);
8797   for (i = 0; i < argc; ++i)
8798     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8799
8800   return list;
8801 }
8802
8803 static PyObject *
8804 put_table (char * const * const argv)
8805 {
8806   PyObject *list, *item;
8807   int argc, i;
8808
8809   for (argc = 0; argv[argc] != NULL; ++argc)
8810     ;
8811
8812   list = PyList_New (argc >> 1);
8813   for (i = 0; i < argc; i += 2) {
8814     item = PyTuple_New (2);
8815     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8816     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8817     PyList_SetItem (list, i >> 1, item);
8818   }
8819
8820   return list;
8821 }
8822
8823 static void
8824 free_strings (char **argv)
8825 {
8826   int argc;
8827
8828   for (argc = 0; argv[argc] != NULL; ++argc)
8829     free (argv[argc]);
8830   free (argv);
8831 }
8832
8833 static PyObject *
8834 py_guestfs_create (PyObject *self, PyObject *args)
8835 {
8836   guestfs_h *g;
8837
8838   g = guestfs_create ();
8839   if (g == NULL) {
8840     PyErr_SetString (PyExc_RuntimeError,
8841                      \"guestfs.create: failed to allocate handle\");
8842     return NULL;
8843   }
8844   guestfs_set_error_handler (g, NULL, NULL);
8845   return put_handle (g);
8846 }
8847
8848 static PyObject *
8849 py_guestfs_close (PyObject *self, PyObject *args)
8850 {
8851   PyObject *py_g;
8852   guestfs_h *g;
8853
8854   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8855     return NULL;
8856   g = get_handle (py_g);
8857
8858   guestfs_close (g);
8859
8860   Py_INCREF (Py_None);
8861   return Py_None;
8862 }
8863
8864 ";
8865
8866   let emit_put_list_function typ =
8867     pr "static PyObject *\n";
8868     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8869     pr "{\n";
8870     pr "  PyObject *list;\n";
8871     pr "  int i;\n";
8872     pr "\n";
8873     pr "  list = PyList_New (%ss->len);\n" typ;
8874     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8875     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8876     pr "  return list;\n";
8877     pr "};\n";
8878     pr "\n"
8879   in
8880
8881   (* Structures, turned into Python dictionaries. *)
8882   List.iter (
8883     fun (typ, cols) ->
8884       pr "static PyObject *\n";
8885       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8886       pr "{\n";
8887       pr "  PyObject *dict;\n";
8888       pr "\n";
8889       pr "  dict = PyDict_New ();\n";
8890       List.iter (
8891         function
8892         | name, FString ->
8893             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8894             pr "                        PyString_FromString (%s->%s));\n"
8895               typ name
8896         | name, FBuffer ->
8897             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8898             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8899               typ name typ name
8900         | name, FUUID ->
8901             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8902             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8903               typ name
8904         | name, (FBytes|FUInt64) ->
8905             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8906             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8907               typ name
8908         | name, FInt64 ->
8909             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8910             pr "                        PyLong_FromLongLong (%s->%s));\n"
8911               typ name
8912         | name, FUInt32 ->
8913             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8914             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8915               typ name
8916         | name, FInt32 ->
8917             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8918             pr "                        PyLong_FromLong (%s->%s));\n"
8919               typ name
8920         | name, FOptPercent ->
8921             pr "  if (%s->%s >= 0)\n" typ name;
8922             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8923             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8924               typ name;
8925             pr "  else {\n";
8926             pr "    Py_INCREF (Py_None);\n";
8927             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8928             pr "  }\n"
8929         | name, FChar ->
8930             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8931             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8932       ) cols;
8933       pr "  return dict;\n";
8934       pr "};\n";
8935       pr "\n";
8936
8937   ) structs;
8938
8939   (* Emit a put_TYPE_list function definition only if that function is used. *)
8940   List.iter (
8941     function
8942     | typ, (RStructListOnly | RStructAndList) ->
8943         (* generate the function for typ *)
8944         emit_put_list_function typ
8945     | typ, _ -> () (* empty *)
8946   ) (rstructs_used_by all_functions);
8947
8948   (* Python wrapper functions. *)
8949   List.iter (
8950     fun (name, style, _, _, _, _, _) ->
8951       pr "static PyObject *\n";
8952       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8953       pr "{\n";
8954
8955       pr "  PyObject *py_g;\n";
8956       pr "  guestfs_h *g;\n";
8957       pr "  PyObject *py_r;\n";
8958
8959       let error_code =
8960         match fst style with
8961         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8962         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8963         | RConstString _ | RConstOptString _ ->
8964             pr "  const char *r;\n"; "NULL"
8965         | RString _ -> pr "  char *r;\n"; "NULL"
8966         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8967         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8968         | RStructList (_, typ) ->
8969             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8970         | RBufferOut _ ->
8971             pr "  char *r;\n";
8972             pr "  size_t size;\n";
8973             "NULL" in
8974
8975       List.iter (
8976         function
8977         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8978             pr "  const char *%s;\n" n
8979         | OptString n -> pr "  const char *%s;\n" n
8980         | StringList n | DeviceList n ->
8981             pr "  PyObject *py_%s;\n" n;
8982             pr "  char **%s;\n" n
8983         | Bool n -> pr "  int %s;\n" n
8984         | Int n -> pr "  int %s;\n" n
8985         | Int64 n -> pr "  long long %s;\n" n
8986       ) (snd style);
8987
8988       pr "\n";
8989
8990       (* Convert the parameters. *)
8991       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8992       List.iter (
8993         function
8994         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8995         | OptString _ -> pr "z"
8996         | StringList _ | DeviceList _ -> pr "O"
8997         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8998         | Int _ -> pr "i"
8999         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9000                              * emulate C's int/long/long long in Python?
9001                              *)
9002       ) (snd style);
9003       pr ":guestfs_%s\",\n" name;
9004       pr "                         &py_g";
9005       List.iter (
9006         function
9007         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9008         | OptString n -> pr ", &%s" n
9009         | StringList n | DeviceList n -> pr ", &py_%s" n
9010         | Bool n -> pr ", &%s" n
9011         | Int n -> pr ", &%s" n
9012         | Int64 n -> pr ", &%s" n
9013       ) (snd style);
9014
9015       pr "))\n";
9016       pr "    return NULL;\n";
9017
9018       pr "  g = get_handle (py_g);\n";
9019       List.iter (
9020         function
9021         | Pathname _ | Device _ | Dev_or_Path _ | String _
9022         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9023         | StringList n | DeviceList n ->
9024             pr "  %s = get_string_list (py_%s);\n" n n;
9025             pr "  if (!%s) return NULL;\n" n
9026       ) (snd style);
9027
9028       pr "\n";
9029
9030       pr "  r = guestfs_%s " name;
9031       generate_c_call_args ~handle:"g" style;
9032       pr ";\n";
9033
9034       List.iter (
9035         function
9036         | Pathname _ | Device _ | Dev_or_Path _ | String _
9037         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9038         | StringList n | DeviceList n ->
9039             pr "  free (%s);\n" n
9040       ) (snd style);
9041
9042       pr "  if (r == %s) {\n" error_code;
9043       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9044       pr "    return NULL;\n";
9045       pr "  }\n";
9046       pr "\n";
9047
9048       (match fst style with
9049        | RErr ->
9050            pr "  Py_INCREF (Py_None);\n";
9051            pr "  py_r = Py_None;\n"
9052        | RInt _
9053        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9054        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9055        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9056        | RConstOptString _ ->
9057            pr "  if (r)\n";
9058            pr "    py_r = PyString_FromString (r);\n";
9059            pr "  else {\n";
9060            pr "    Py_INCREF (Py_None);\n";
9061            pr "    py_r = Py_None;\n";
9062            pr "  }\n"
9063        | RString _ ->
9064            pr "  py_r = PyString_FromString (r);\n";
9065            pr "  free (r);\n"
9066        | RStringList _ ->
9067            pr "  py_r = put_string_list (r);\n";
9068            pr "  free_strings (r);\n"
9069        | RStruct (_, typ) ->
9070            pr "  py_r = put_%s (r);\n" typ;
9071            pr "  guestfs_free_%s (r);\n" typ
9072        | RStructList (_, typ) ->
9073            pr "  py_r = put_%s_list (r);\n" typ;
9074            pr "  guestfs_free_%s_list (r);\n" typ
9075        | RHashtable n ->
9076            pr "  py_r = put_table (r);\n";
9077            pr "  free_strings (r);\n"
9078        | RBufferOut _ ->
9079            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9080            pr "  free (r);\n"
9081       );
9082
9083       pr "  return py_r;\n";
9084       pr "}\n";
9085       pr "\n"
9086   ) all_functions;
9087
9088   (* Table of functions. *)
9089   pr "static PyMethodDef methods[] = {\n";
9090   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9091   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9092   List.iter (
9093     fun (name, _, _, _, _, _, _) ->
9094       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9095         name name
9096   ) all_functions;
9097   pr "  { NULL, NULL, 0, NULL }\n";
9098   pr "};\n";
9099   pr "\n";
9100
9101   (* Init function. *)
9102   pr "\
9103 void
9104 initlibguestfsmod (void)
9105 {
9106   static int initialized = 0;
9107
9108   if (initialized) return;
9109   Py_InitModule ((char *) \"libguestfsmod\", methods);
9110   initialized = 1;
9111 }
9112 "
9113
9114 (* Generate Python module. *)
9115 and generate_python_py () =
9116   generate_header HashStyle LGPLv2plus;
9117
9118   pr "\
9119 u\"\"\"Python bindings for libguestfs
9120
9121 import guestfs
9122 g = guestfs.GuestFS ()
9123 g.add_drive (\"guest.img\")
9124 g.launch ()
9125 parts = g.list_partitions ()
9126
9127 The guestfs module provides a Python binding to the libguestfs API
9128 for examining and modifying virtual machine disk images.
9129
9130 Amongst the things this is good for: making batch configuration
9131 changes to guests, getting disk used/free statistics (see also:
9132 virt-df), migrating between virtualization systems (see also:
9133 virt-p2v), performing partial backups, performing partial guest
9134 clones, cloning guests and changing registry/UUID/hostname info, and
9135 much else besides.
9136
9137 Libguestfs uses Linux kernel and qemu code, and can access any type of
9138 guest filesystem that Linux and qemu can, including but not limited
9139 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9140 schemes, qcow, qcow2, vmdk.
9141
9142 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9143 LVs, what filesystem is in each LV, etc.).  It can also run commands
9144 in the context of the guest.  Also you can access filesystems over
9145 FUSE.
9146
9147 Errors which happen while using the API are turned into Python
9148 RuntimeError exceptions.
9149
9150 To create a guestfs handle you usually have to perform the following
9151 sequence of calls:
9152
9153 # Create the handle, call add_drive at least once, and possibly
9154 # several times if the guest has multiple block devices:
9155 g = guestfs.GuestFS ()
9156 g.add_drive (\"guest.img\")
9157
9158 # Launch the qemu subprocess and wait for it to become ready:
9159 g.launch ()
9160
9161 # Now you can issue commands, for example:
9162 logvols = g.lvs ()
9163
9164 \"\"\"
9165
9166 import libguestfsmod
9167
9168 class GuestFS:
9169     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9170
9171     def __init__ (self):
9172         \"\"\"Create a new libguestfs handle.\"\"\"
9173         self._o = libguestfsmod.create ()
9174
9175     def __del__ (self):
9176         libguestfsmod.close (self._o)
9177
9178 ";
9179
9180   List.iter (
9181     fun (name, style, _, flags, _, _, longdesc) ->
9182       pr "    def %s " name;
9183       generate_py_call_args ~handle:"self" (snd style);
9184       pr ":\n";
9185
9186       if not (List.mem NotInDocs flags) then (
9187         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9188         let doc =
9189           match fst style with
9190           | RErr | RInt _ | RInt64 _ | RBool _
9191           | RConstOptString _ | RConstString _
9192           | RString _ | RBufferOut _ -> doc
9193           | RStringList _ ->
9194               doc ^ "\n\nThis function returns a list of strings."
9195           | RStruct (_, typ) ->
9196               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9197           | RStructList (_, typ) ->
9198               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9199           | RHashtable _ ->
9200               doc ^ "\n\nThis function returns a dictionary." in
9201         let doc =
9202           if List.mem ProtocolLimitWarning flags then
9203             doc ^ "\n\n" ^ protocol_limit_warning
9204           else doc in
9205         let doc =
9206           if List.mem DangerWillRobinson flags then
9207             doc ^ "\n\n" ^ danger_will_robinson
9208           else doc in
9209         let doc =
9210           match deprecation_notice flags with
9211           | None -> doc
9212           | Some txt -> doc ^ "\n\n" ^ txt in
9213         let doc = pod2text ~width:60 name doc in
9214         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9215         let doc = String.concat "\n        " doc in
9216         pr "        u\"\"\"%s\"\"\"\n" doc;
9217       );
9218       pr "        return libguestfsmod.%s " name;
9219       generate_py_call_args ~handle:"self._o" (snd style);
9220       pr "\n";
9221       pr "\n";
9222   ) all_functions
9223
9224 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9225 and generate_py_call_args ~handle args =
9226   pr "(%s" handle;
9227   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9228   pr ")"
9229
9230 (* Useful if you need the longdesc POD text as plain text.  Returns a
9231  * list of lines.
9232  *
9233  * Because this is very slow (the slowest part of autogeneration),
9234  * we memoize the results.
9235  *)
9236 and pod2text ~width name longdesc =
9237   let key = width, name, longdesc in
9238   try Hashtbl.find pod2text_memo key
9239   with Not_found ->
9240     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9241     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9242     close_out chan;
9243     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9244     let chan = open_process_in cmd in
9245     let lines = ref [] in
9246     let rec loop i =
9247       let line = input_line chan in
9248       if i = 1 then             (* discard the first line of output *)
9249         loop (i+1)
9250       else (
9251         let line = triml line in
9252         lines := line :: !lines;
9253         loop (i+1)
9254       ) in
9255     let lines = try loop 1 with End_of_file -> List.rev !lines in
9256     unlink filename;
9257     (match close_process_in chan with
9258      | WEXITED 0 -> ()
9259      | WEXITED i ->
9260          failwithf "pod2text: process exited with non-zero status (%d)" i
9261      | WSIGNALED i | WSTOPPED i ->
9262          failwithf "pod2text: process signalled or stopped by signal %d" i
9263     );
9264     Hashtbl.add pod2text_memo key lines;
9265     pod2text_memo_updated ();
9266     lines
9267
9268 (* Generate ruby bindings. *)
9269 and generate_ruby_c () =
9270   generate_header CStyle LGPLv2plus;
9271
9272   pr "\
9273 #include <stdio.h>
9274 #include <stdlib.h>
9275
9276 #include <ruby.h>
9277
9278 #include \"guestfs.h\"
9279
9280 #include \"extconf.h\"
9281
9282 /* For Ruby < 1.9 */
9283 #ifndef RARRAY_LEN
9284 #define RARRAY_LEN(r) (RARRAY((r))->len)
9285 #endif
9286
9287 static VALUE m_guestfs;                 /* guestfs module */
9288 static VALUE c_guestfs;                 /* guestfs_h handle */
9289 static VALUE e_Error;                   /* used for all errors */
9290
9291 static void ruby_guestfs_free (void *p)
9292 {
9293   if (!p) return;
9294   guestfs_close ((guestfs_h *) p);
9295 }
9296
9297 static VALUE ruby_guestfs_create (VALUE m)
9298 {
9299   guestfs_h *g;
9300
9301   g = guestfs_create ();
9302   if (!g)
9303     rb_raise (e_Error, \"failed to create guestfs handle\");
9304
9305   /* Don't print error messages to stderr by default. */
9306   guestfs_set_error_handler (g, NULL, NULL);
9307
9308   /* Wrap it, and make sure the close function is called when the
9309    * handle goes away.
9310    */
9311   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9312 }
9313
9314 static VALUE ruby_guestfs_close (VALUE gv)
9315 {
9316   guestfs_h *g;
9317   Data_Get_Struct (gv, guestfs_h, g);
9318
9319   ruby_guestfs_free (g);
9320   DATA_PTR (gv) = NULL;
9321
9322   return Qnil;
9323 }
9324
9325 ";
9326
9327   List.iter (
9328     fun (name, style, _, _, _, _, _) ->
9329       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9330       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9331       pr ")\n";
9332       pr "{\n";
9333       pr "  guestfs_h *g;\n";
9334       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9335       pr "  if (!g)\n";
9336       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9337         name;
9338       pr "\n";
9339
9340       List.iter (
9341         function
9342         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9343             pr "  Check_Type (%sv, T_STRING);\n" n;
9344             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9345             pr "  if (!%s)\n" n;
9346             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9347             pr "              \"%s\", \"%s\");\n" n name
9348         | OptString n ->
9349             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9350         | StringList n | DeviceList n ->
9351             pr "  char **%s;\n" n;
9352             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9353             pr "  {\n";
9354             pr "    int i, len;\n";
9355             pr "    len = RARRAY_LEN (%sv);\n" n;
9356             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9357               n;
9358             pr "    for (i = 0; i < len; ++i) {\n";
9359             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9360             pr "      %s[i] = StringValueCStr (v);\n" n;
9361             pr "    }\n";
9362             pr "    %s[len] = NULL;\n" n;
9363             pr "  }\n";
9364         | Bool n ->
9365             pr "  int %s = RTEST (%sv);\n" n n
9366         | Int n ->
9367             pr "  int %s = NUM2INT (%sv);\n" n n
9368         | Int64 n ->
9369             pr "  long long %s = NUM2LL (%sv);\n" n n
9370       ) (snd style);
9371       pr "\n";
9372
9373       let error_code =
9374         match fst style with
9375         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9376         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9377         | RConstString _ | RConstOptString _ ->
9378             pr "  const char *r;\n"; "NULL"
9379         | RString _ -> pr "  char *r;\n"; "NULL"
9380         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9381         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9382         | RStructList (_, typ) ->
9383             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9384         | RBufferOut _ ->
9385             pr "  char *r;\n";
9386             pr "  size_t size;\n";
9387             "NULL" in
9388       pr "\n";
9389
9390       pr "  r = guestfs_%s " name;
9391       generate_c_call_args ~handle:"g" style;
9392       pr ";\n";
9393
9394       List.iter (
9395         function
9396         | Pathname _ | Device _ | Dev_or_Path _ | String _
9397         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9398         | StringList n | DeviceList n ->
9399             pr "  free (%s);\n" n
9400       ) (snd style);
9401
9402       pr "  if (r == %s)\n" error_code;
9403       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9404       pr "\n";
9405
9406       (match fst style with
9407        | RErr ->
9408            pr "  return Qnil;\n"
9409        | RInt _ | RBool _ ->
9410            pr "  return INT2NUM (r);\n"
9411        | RInt64 _ ->
9412            pr "  return ULL2NUM (r);\n"
9413        | RConstString _ ->
9414            pr "  return rb_str_new2 (r);\n";
9415        | RConstOptString _ ->
9416            pr "  if (r)\n";
9417            pr "    return rb_str_new2 (r);\n";
9418            pr "  else\n";
9419            pr "    return Qnil;\n";
9420        | RString _ ->
9421            pr "  VALUE rv = rb_str_new2 (r);\n";
9422            pr "  free (r);\n";
9423            pr "  return rv;\n";
9424        | RStringList _ ->
9425            pr "  int i, len = 0;\n";
9426            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9427            pr "  VALUE rv = rb_ary_new2 (len);\n";
9428            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9429            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9430            pr "    free (r[i]);\n";
9431            pr "  }\n";
9432            pr "  free (r);\n";
9433            pr "  return rv;\n"
9434        | RStruct (_, typ) ->
9435            let cols = cols_of_struct typ in
9436            generate_ruby_struct_code typ cols
9437        | RStructList (_, typ) ->
9438            let cols = cols_of_struct typ in
9439            generate_ruby_struct_list_code typ cols
9440        | RHashtable _ ->
9441            pr "  VALUE rv = rb_hash_new ();\n";
9442            pr "  int i;\n";
9443            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9444            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9445            pr "    free (r[i]);\n";
9446            pr "    free (r[i+1]);\n";
9447            pr "  }\n";
9448            pr "  free (r);\n";
9449            pr "  return rv;\n"
9450        | RBufferOut _ ->
9451            pr "  VALUE rv = rb_str_new (r, size);\n";
9452            pr "  free (r);\n";
9453            pr "  return rv;\n";
9454       );
9455
9456       pr "}\n";
9457       pr "\n"
9458   ) all_functions;
9459
9460   pr "\
9461 /* Initialize the module. */
9462 void Init__guestfs ()
9463 {
9464   m_guestfs = rb_define_module (\"Guestfs\");
9465   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9466   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9467
9468   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9469   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9470
9471 ";
9472   (* Define the rest of the methods. *)
9473   List.iter (
9474     fun (name, style, _, _, _, _, _) ->
9475       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9476       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9477   ) all_functions;
9478
9479   pr "}\n"
9480
9481 (* Ruby code to return a struct. *)
9482 and generate_ruby_struct_code typ cols =
9483   pr "  VALUE rv = rb_hash_new ();\n";
9484   List.iter (
9485     function
9486     | name, FString ->
9487         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9488     | name, FBuffer ->
9489         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9490     | name, FUUID ->
9491         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9492     | name, (FBytes|FUInt64) ->
9493         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9494     | name, FInt64 ->
9495         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9496     | name, FUInt32 ->
9497         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9498     | name, FInt32 ->
9499         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9500     | name, FOptPercent ->
9501         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9502     | name, FChar -> (* XXX wrong? *)
9503         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9504   ) cols;
9505   pr "  guestfs_free_%s (r);\n" typ;
9506   pr "  return rv;\n"
9507
9508 (* Ruby code to return a struct list. *)
9509 and generate_ruby_struct_list_code typ cols =
9510   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9511   pr "  int i;\n";
9512   pr "  for (i = 0; i < r->len; ++i) {\n";
9513   pr "    VALUE hv = rb_hash_new ();\n";
9514   List.iter (
9515     function
9516     | name, FString ->
9517         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9518     | name, FBuffer ->
9519         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
9520     | name, FUUID ->
9521         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9522     | name, (FBytes|FUInt64) ->
9523         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9524     | name, FInt64 ->
9525         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9526     | name, FUInt32 ->
9527         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9528     | name, FInt32 ->
9529         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9530     | name, FOptPercent ->
9531         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9532     | name, FChar -> (* XXX wrong? *)
9533         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9534   ) cols;
9535   pr "    rb_ary_push (rv, hv);\n";
9536   pr "  }\n";
9537   pr "  guestfs_free_%s_list (r);\n" typ;
9538   pr "  return rv;\n"
9539
9540 (* Generate Java bindings GuestFS.java file. *)
9541 and generate_java_java () =
9542   generate_header CStyle LGPLv2plus;
9543
9544   pr "\
9545 package com.redhat.et.libguestfs;
9546
9547 import java.util.HashMap;
9548 import com.redhat.et.libguestfs.LibGuestFSException;
9549 import com.redhat.et.libguestfs.PV;
9550 import com.redhat.et.libguestfs.VG;
9551 import com.redhat.et.libguestfs.LV;
9552 import com.redhat.et.libguestfs.Stat;
9553 import com.redhat.et.libguestfs.StatVFS;
9554 import com.redhat.et.libguestfs.IntBool;
9555 import com.redhat.et.libguestfs.Dirent;
9556
9557 /**
9558  * The GuestFS object is a libguestfs handle.
9559  *
9560  * @author rjones
9561  */
9562 public class GuestFS {
9563   // Load the native code.
9564   static {
9565     System.loadLibrary (\"guestfs_jni\");
9566   }
9567
9568   /**
9569    * The native guestfs_h pointer.
9570    */
9571   long g;
9572
9573   /**
9574    * Create a libguestfs handle.
9575    *
9576    * @throws LibGuestFSException
9577    */
9578   public GuestFS () throws LibGuestFSException
9579   {
9580     g = _create ();
9581   }
9582   private native long _create () throws LibGuestFSException;
9583
9584   /**
9585    * Close a libguestfs handle.
9586    *
9587    * You can also leave handles to be collected by the garbage
9588    * collector, but this method ensures that the resources used
9589    * by the handle are freed up immediately.  If you call any
9590    * other methods after closing the handle, you will get an
9591    * exception.
9592    *
9593    * @throws LibGuestFSException
9594    */
9595   public void close () throws LibGuestFSException
9596   {
9597     if (g != 0)
9598       _close (g);
9599     g = 0;
9600   }
9601   private native void _close (long g) throws LibGuestFSException;
9602
9603   public void finalize () throws LibGuestFSException
9604   {
9605     close ();
9606   }
9607
9608 ";
9609
9610   List.iter (
9611     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9612       if not (List.mem NotInDocs flags); then (
9613         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9614         let doc =
9615           if List.mem ProtocolLimitWarning flags then
9616             doc ^ "\n\n" ^ protocol_limit_warning
9617           else doc in
9618         let doc =
9619           if List.mem DangerWillRobinson flags then
9620             doc ^ "\n\n" ^ danger_will_robinson
9621           else doc in
9622         let doc =
9623           match deprecation_notice flags with
9624           | None -> doc
9625           | Some txt -> doc ^ "\n\n" ^ txt in
9626         let doc = pod2text ~width:60 name doc in
9627         let doc = List.map (            (* RHBZ#501883 *)
9628           function
9629           | "" -> "<p>"
9630           | nonempty -> nonempty
9631         ) doc in
9632         let doc = String.concat "\n   * " doc in
9633
9634         pr "  /**\n";
9635         pr "   * %s\n" shortdesc;
9636         pr "   * <p>\n";
9637         pr "   * %s\n" doc;
9638         pr "   * @throws LibGuestFSException\n";
9639         pr "   */\n";
9640         pr "  ";
9641       );
9642       generate_java_prototype ~public:true ~semicolon:false name style;
9643       pr "\n";
9644       pr "  {\n";
9645       pr "    if (g == 0)\n";
9646       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9647         name;
9648       pr "    ";
9649       if fst style <> RErr then pr "return ";
9650       pr "_%s " name;
9651       generate_java_call_args ~handle:"g" (snd style);
9652       pr ";\n";
9653       pr "  }\n";
9654       pr "  ";
9655       generate_java_prototype ~privat:true ~native:true name style;
9656       pr "\n";
9657       pr "\n";
9658   ) all_functions;
9659
9660   pr "}\n"
9661
9662 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9663 and generate_java_call_args ~handle args =
9664   pr "(%s" handle;
9665   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9666   pr ")"
9667
9668 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9669     ?(semicolon=true) name style =
9670   if privat then pr "private ";
9671   if public then pr "public ";
9672   if native then pr "native ";
9673
9674   (* return type *)
9675   (match fst style with
9676    | RErr -> pr "void ";
9677    | RInt _ -> pr "int ";
9678    | RInt64 _ -> pr "long ";
9679    | RBool _ -> pr "boolean ";
9680    | RConstString _ | RConstOptString _ | RString _
9681    | RBufferOut _ -> pr "String ";
9682    | RStringList _ -> pr "String[] ";
9683    | RStruct (_, typ) ->
9684        let name = java_name_of_struct typ in
9685        pr "%s " name;
9686    | RStructList (_, typ) ->
9687        let name = java_name_of_struct typ in
9688        pr "%s[] " name;
9689    | RHashtable _ -> pr "HashMap<String,String> ";
9690   );
9691
9692   if native then pr "_%s " name else pr "%s " name;
9693   pr "(";
9694   let needs_comma = ref false in
9695   if native then (
9696     pr "long g";
9697     needs_comma := true
9698   );
9699
9700   (* args *)
9701   List.iter (
9702     fun arg ->
9703       if !needs_comma then pr ", ";
9704       needs_comma := true;
9705
9706       match arg with
9707       | Pathname n
9708       | Device n | Dev_or_Path n
9709       | String n
9710       | OptString n
9711       | FileIn n
9712       | FileOut n ->
9713           pr "String %s" n
9714       | StringList n | DeviceList n ->
9715           pr "String[] %s" n
9716       | Bool n ->
9717           pr "boolean %s" n
9718       | Int n ->
9719           pr "int %s" n
9720       | Int64 n ->
9721           pr "long %s" n
9722   ) (snd style);
9723
9724   pr ")\n";
9725   pr "    throws LibGuestFSException";
9726   if semicolon then pr ";"
9727
9728 and generate_java_struct jtyp cols () =
9729   generate_header CStyle LGPLv2plus;
9730
9731   pr "\
9732 package com.redhat.et.libguestfs;
9733
9734 /**
9735  * Libguestfs %s structure.
9736  *
9737  * @author rjones
9738  * @see GuestFS
9739  */
9740 public class %s {
9741 " jtyp jtyp;
9742
9743   List.iter (
9744     function
9745     | name, FString
9746     | name, FUUID
9747     | name, FBuffer -> pr "  public String %s;\n" name
9748     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9749     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9750     | name, FChar -> pr "  public char %s;\n" name
9751     | name, FOptPercent ->
9752         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9753         pr "  public float %s;\n" name
9754   ) cols;
9755
9756   pr "}\n"
9757
9758 and generate_java_c () =
9759   generate_header CStyle LGPLv2plus;
9760
9761   pr "\
9762 #include <stdio.h>
9763 #include <stdlib.h>
9764 #include <string.h>
9765
9766 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9767 #include \"guestfs.h\"
9768
9769 /* Note that this function returns.  The exception is not thrown
9770  * until after the wrapper function returns.
9771  */
9772 static void
9773 throw_exception (JNIEnv *env, const char *msg)
9774 {
9775   jclass cl;
9776   cl = (*env)->FindClass (env,
9777                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9778   (*env)->ThrowNew (env, cl, msg);
9779 }
9780
9781 JNIEXPORT jlong JNICALL
9782 Java_com_redhat_et_libguestfs_GuestFS__1create
9783   (JNIEnv *env, jobject obj)
9784 {
9785   guestfs_h *g;
9786
9787   g = guestfs_create ();
9788   if (g == NULL) {
9789     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9790     return 0;
9791   }
9792   guestfs_set_error_handler (g, NULL, NULL);
9793   return (jlong) (long) g;
9794 }
9795
9796 JNIEXPORT void JNICALL
9797 Java_com_redhat_et_libguestfs_GuestFS__1close
9798   (JNIEnv *env, jobject obj, jlong jg)
9799 {
9800   guestfs_h *g = (guestfs_h *) (long) jg;
9801   guestfs_close (g);
9802 }
9803
9804 ";
9805
9806   List.iter (
9807     fun (name, style, _, _, _, _, _) ->
9808       pr "JNIEXPORT ";
9809       (match fst style with
9810        | RErr -> pr "void ";
9811        | RInt _ -> pr "jint ";
9812        | RInt64 _ -> pr "jlong ";
9813        | RBool _ -> pr "jboolean ";
9814        | RConstString _ | RConstOptString _ | RString _
9815        | RBufferOut _ -> pr "jstring ";
9816        | RStruct _ | RHashtable _ ->
9817            pr "jobject ";
9818        | RStringList _ | RStructList _ ->
9819            pr "jobjectArray ";
9820       );
9821       pr "JNICALL\n";
9822       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9823       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9824       pr "\n";
9825       pr "  (JNIEnv *env, jobject obj, jlong jg";
9826       List.iter (
9827         function
9828         | Pathname n
9829         | Device n | Dev_or_Path n
9830         | String n
9831         | OptString n
9832         | FileIn n
9833         | FileOut n ->
9834             pr ", jstring j%s" n
9835         | StringList n | DeviceList n ->
9836             pr ", jobjectArray j%s" n
9837         | Bool n ->
9838             pr ", jboolean j%s" n
9839         | Int n ->
9840             pr ", jint j%s" n
9841         | Int64 n ->
9842             pr ", jlong j%s" n
9843       ) (snd style);
9844       pr ")\n";
9845       pr "{\n";
9846       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9847       let error_code, no_ret =
9848         match fst style with
9849         | RErr -> pr "  int r;\n"; "-1", ""
9850         | RBool _
9851         | RInt _ -> pr "  int r;\n"; "-1", "0"
9852         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9853         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9854         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9855         | RString _ ->
9856             pr "  jstring jr;\n";
9857             pr "  char *r;\n"; "NULL", "NULL"
9858         | RStringList _ ->
9859             pr "  jobjectArray jr;\n";
9860             pr "  int r_len;\n";
9861             pr "  jclass cl;\n";
9862             pr "  jstring jstr;\n";
9863             pr "  char **r;\n"; "NULL", "NULL"
9864         | RStruct (_, typ) ->
9865             pr "  jobject jr;\n";
9866             pr "  jclass cl;\n";
9867             pr "  jfieldID fl;\n";
9868             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9869         | RStructList (_, typ) ->
9870             pr "  jobjectArray jr;\n";
9871             pr "  jclass cl;\n";
9872             pr "  jfieldID fl;\n";
9873             pr "  jobject jfl;\n";
9874             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9875         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9876         | RBufferOut _ ->
9877             pr "  jstring jr;\n";
9878             pr "  char *r;\n";
9879             pr "  size_t size;\n";
9880             "NULL", "NULL" in
9881       List.iter (
9882         function
9883         | Pathname n
9884         | Device n | Dev_or_Path n
9885         | String n
9886         | OptString n
9887         | FileIn n
9888         | FileOut n ->
9889             pr "  const char *%s;\n" n
9890         | StringList n | DeviceList n ->
9891             pr "  int %s_len;\n" n;
9892             pr "  const char **%s;\n" n
9893         | Bool n
9894         | Int n ->
9895             pr "  int %s;\n" n
9896         | Int64 n ->
9897             pr "  int64_t %s;\n" n
9898       ) (snd style);
9899
9900       let needs_i =
9901         (match fst style with
9902          | RStringList _ | RStructList _ -> true
9903          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9904          | RConstOptString _
9905          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9906           List.exists (function
9907                        | StringList _ -> true
9908                        | DeviceList _ -> true
9909                        | _ -> false) (snd style) in
9910       if needs_i then
9911         pr "  int i;\n";
9912
9913       pr "\n";
9914
9915       (* Get the parameters. *)
9916       List.iter (
9917         function
9918         | Pathname n
9919         | Device n | Dev_or_Path n
9920         | String n
9921         | FileIn n
9922         | FileOut n ->
9923             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9924         | OptString n ->
9925             (* This is completely undocumented, but Java null becomes
9926              * a NULL parameter.
9927              *)
9928             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9929         | StringList n | DeviceList n ->
9930             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9931             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9932             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9933             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9934               n;
9935             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9936             pr "  }\n";
9937             pr "  %s[%s_len] = NULL;\n" n n;
9938         | Bool n
9939         | Int n
9940         | Int64 n ->
9941             pr "  %s = j%s;\n" n n
9942       ) (snd style);
9943
9944       (* Make the call. *)
9945       pr "  r = guestfs_%s " name;
9946       generate_c_call_args ~handle:"g" style;
9947       pr ";\n";
9948
9949       (* Release the parameters. *)
9950       List.iter (
9951         function
9952         | Pathname n
9953         | Device n | Dev_or_Path n
9954         | String n
9955         | FileIn n
9956         | FileOut n ->
9957             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9958         | OptString n ->
9959             pr "  if (j%s)\n" n;
9960             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9961         | StringList n | DeviceList n ->
9962             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9963             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9964               n;
9965             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9966             pr "  }\n";
9967             pr "  free (%s);\n" n
9968         | Bool n
9969         | Int n
9970         | Int64 n -> ()
9971       ) (snd style);
9972
9973       (* Check for errors. *)
9974       pr "  if (r == %s) {\n" error_code;
9975       pr "    throw_exception (env, guestfs_last_error (g));\n";
9976       pr "    return %s;\n" no_ret;
9977       pr "  }\n";
9978
9979       (* Return value. *)
9980       (match fst style with
9981        | RErr -> ()
9982        | RInt _ -> pr "  return (jint) r;\n"
9983        | RBool _ -> pr "  return (jboolean) r;\n"
9984        | RInt64 _ -> pr "  return (jlong) r;\n"
9985        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9986        | RConstOptString _ ->
9987            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9988        | RString _ ->
9989            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9990            pr "  free (r);\n";
9991            pr "  return jr;\n"
9992        | RStringList _ ->
9993            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9994            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9995            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9996            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9997            pr "  for (i = 0; i < r_len; ++i) {\n";
9998            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9999            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10000            pr "    free (r[i]);\n";
10001            pr "  }\n";
10002            pr "  free (r);\n";
10003            pr "  return jr;\n"
10004        | RStruct (_, typ) ->
10005            let jtyp = java_name_of_struct typ in
10006            let cols = cols_of_struct typ in
10007            generate_java_struct_return typ jtyp cols
10008        | RStructList (_, typ) ->
10009            let jtyp = java_name_of_struct typ in
10010            let cols = cols_of_struct typ in
10011            generate_java_struct_list_return typ jtyp cols
10012        | RHashtable _ ->
10013            (* XXX *)
10014            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10015            pr "  return NULL;\n"
10016        | RBufferOut _ ->
10017            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10018            pr "  free (r);\n";
10019            pr "  return jr;\n"
10020       );
10021
10022       pr "}\n";
10023       pr "\n"
10024   ) all_functions
10025
10026 and generate_java_struct_return typ jtyp cols =
10027   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10028   pr "  jr = (*env)->AllocObject (env, cl);\n";
10029   List.iter (
10030     function
10031     | name, FString ->
10032         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10033         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10034     | name, FUUID ->
10035         pr "  {\n";
10036         pr "    char s[33];\n";
10037         pr "    memcpy (s, r->%s, 32);\n" name;
10038         pr "    s[32] = 0;\n";
10039         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10040         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10041         pr "  }\n";
10042     | name, FBuffer ->
10043         pr "  {\n";
10044         pr "    int len = r->%s_len;\n" name;
10045         pr "    char s[len+1];\n";
10046         pr "    memcpy (s, r->%s, len);\n" name;
10047         pr "    s[len] = 0;\n";
10048         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10049         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10050         pr "  }\n";
10051     | name, (FBytes|FUInt64|FInt64) ->
10052         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10053         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10054     | name, (FUInt32|FInt32) ->
10055         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10056         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10057     | name, FOptPercent ->
10058         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10059         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10060     | name, FChar ->
10061         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10062         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10063   ) cols;
10064   pr "  free (r);\n";
10065   pr "  return jr;\n"
10066
10067 and generate_java_struct_list_return typ jtyp cols =
10068   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10069   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10070   pr "  for (i = 0; i < r->len; ++i) {\n";
10071   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10072   List.iter (
10073     function
10074     | name, FString ->
10075         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10076         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10077     | name, FUUID ->
10078         pr "    {\n";
10079         pr "      char s[33];\n";
10080         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10081         pr "      s[32] = 0;\n";
10082         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10083         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10084         pr "    }\n";
10085     | name, FBuffer ->
10086         pr "    {\n";
10087         pr "      int len = r->val[i].%s_len;\n" name;
10088         pr "      char s[len+1];\n";
10089         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10090         pr "      s[len] = 0;\n";
10091         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10092         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10093         pr "    }\n";
10094     | name, (FBytes|FUInt64|FInt64) ->
10095         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10096         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10097     | name, (FUInt32|FInt32) ->
10098         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10099         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10100     | name, FOptPercent ->
10101         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10102         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10103     | name, FChar ->
10104         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10105         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10106   ) cols;
10107   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10108   pr "  }\n";
10109   pr "  guestfs_free_%s_list (r);\n" typ;
10110   pr "  return jr;\n"
10111
10112 and generate_java_makefile_inc () =
10113   generate_header HashStyle GPLv2plus;
10114
10115   pr "java_built_sources = \\\n";
10116   List.iter (
10117     fun (typ, jtyp) ->
10118         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10119   ) java_structs;
10120   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10121
10122 and generate_haskell_hs () =
10123   generate_header HaskellStyle LGPLv2plus;
10124
10125   (* XXX We only know how to generate partial FFI for Haskell
10126    * at the moment.  Please help out!
10127    *)
10128   let can_generate style =
10129     match style with
10130     | RErr, _
10131     | RInt _, _
10132     | RInt64 _, _ -> true
10133     | RBool _, _
10134     | RConstString _, _
10135     | RConstOptString _, _
10136     | RString _, _
10137     | RStringList _, _
10138     | RStruct _, _
10139     | RStructList _, _
10140     | RHashtable _, _
10141     | RBufferOut _, _ -> false in
10142
10143   pr "\
10144 {-# INCLUDE <guestfs.h> #-}
10145 {-# LANGUAGE ForeignFunctionInterface #-}
10146
10147 module Guestfs (
10148   create";
10149
10150   (* List out the names of the actions we want to export. *)
10151   List.iter (
10152     fun (name, style, _, _, _, _, _) ->
10153       if can_generate style then pr ",\n  %s" name
10154   ) all_functions;
10155
10156   pr "
10157   ) where
10158
10159 -- Unfortunately some symbols duplicate ones already present
10160 -- in Prelude.  We don't know which, so we hard-code a list
10161 -- here.
10162 import Prelude hiding (truncate)
10163
10164 import Foreign
10165 import Foreign.C
10166 import Foreign.C.Types
10167 import IO
10168 import Control.Exception
10169 import Data.Typeable
10170
10171 data GuestfsS = GuestfsS            -- represents the opaque C struct
10172 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10173 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10174
10175 -- XXX define properly later XXX
10176 data PV = PV
10177 data VG = VG
10178 data LV = LV
10179 data IntBool = IntBool
10180 data Stat = Stat
10181 data StatVFS = StatVFS
10182 data Hashtable = Hashtable
10183
10184 foreign import ccall unsafe \"guestfs_create\" c_create
10185   :: IO GuestfsP
10186 foreign import ccall unsafe \"&guestfs_close\" c_close
10187   :: FunPtr (GuestfsP -> IO ())
10188 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10189   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10190
10191 create :: IO GuestfsH
10192 create = do
10193   p <- c_create
10194   c_set_error_handler p nullPtr nullPtr
10195   h <- newForeignPtr c_close p
10196   return h
10197
10198 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10199   :: GuestfsP -> IO CString
10200
10201 -- last_error :: GuestfsH -> IO (Maybe String)
10202 -- last_error h = do
10203 --   str <- withForeignPtr h (\\p -> c_last_error p)
10204 --   maybePeek peekCString str
10205
10206 last_error :: GuestfsH -> IO (String)
10207 last_error h = do
10208   str <- withForeignPtr h (\\p -> c_last_error p)
10209   if (str == nullPtr)
10210     then return \"no error\"
10211     else peekCString str
10212
10213 ";
10214
10215   (* Generate wrappers for each foreign function. *)
10216   List.iter (
10217     fun (name, style, _, _, _, _, _) ->
10218       if can_generate style then (
10219         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10220         pr "  :: ";
10221         generate_haskell_prototype ~handle:"GuestfsP" style;
10222         pr "\n";
10223         pr "\n";
10224         pr "%s :: " name;
10225         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10226         pr "\n";
10227         pr "%s %s = do\n" name
10228           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10229         pr "  r <- ";
10230         (* Convert pointer arguments using with* functions. *)
10231         List.iter (
10232           function
10233           | FileIn n
10234           | FileOut n
10235           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10236           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10237           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10238           | Bool _ | Int _ | Int64 _ -> ()
10239         ) (snd style);
10240         (* Convert integer arguments. *)
10241         let args =
10242           List.map (
10243             function
10244             | Bool n -> sprintf "(fromBool %s)" n
10245             | Int n -> sprintf "(fromIntegral %s)" n
10246             | Int64 n -> sprintf "(fromIntegral %s)" n
10247             | FileIn n | FileOut n
10248             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10249           ) (snd style) in
10250         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10251           (String.concat " " ("p" :: args));
10252         (match fst style with
10253          | RErr | RInt _ | RInt64 _ | RBool _ ->
10254              pr "  if (r == -1)\n";
10255              pr "    then do\n";
10256              pr "      err <- last_error h\n";
10257              pr "      fail err\n";
10258          | RConstString _ | RConstOptString _ | RString _
10259          | RStringList _ | RStruct _
10260          | RStructList _ | RHashtable _ | RBufferOut _ ->
10261              pr "  if (r == nullPtr)\n";
10262              pr "    then do\n";
10263              pr "      err <- last_error h\n";
10264              pr "      fail err\n";
10265         );
10266         (match fst style with
10267          | RErr ->
10268              pr "    else return ()\n"
10269          | RInt _ ->
10270              pr "    else return (fromIntegral r)\n"
10271          | RInt64 _ ->
10272              pr "    else return (fromIntegral r)\n"
10273          | RBool _ ->
10274              pr "    else return (toBool r)\n"
10275          | RConstString _
10276          | RConstOptString _
10277          | RString _
10278          | RStringList _
10279          | RStruct _
10280          | RStructList _
10281          | RHashtable _
10282          | RBufferOut _ ->
10283              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10284         );
10285         pr "\n";
10286       )
10287   ) all_functions
10288
10289 and generate_haskell_prototype ~handle ?(hs = false) style =
10290   pr "%s -> " handle;
10291   let string = if hs then "String" else "CString" in
10292   let int = if hs then "Int" else "CInt" in
10293   let bool = if hs then "Bool" else "CInt" in
10294   let int64 = if hs then "Integer" else "Int64" in
10295   List.iter (
10296     fun arg ->
10297       (match arg with
10298        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10299        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10300        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10301        | Bool _ -> pr "%s" bool
10302        | Int _ -> pr "%s" int
10303        | Int64 _ -> pr "%s" int
10304        | FileIn _ -> pr "%s" string
10305        | FileOut _ -> pr "%s" string
10306       );
10307       pr " -> ";
10308   ) (snd style);
10309   pr "IO (";
10310   (match fst style with
10311    | RErr -> if not hs then pr "CInt"
10312    | RInt _ -> pr "%s" int
10313    | RInt64 _ -> pr "%s" int64
10314    | RBool _ -> pr "%s" bool
10315    | RConstString _ -> pr "%s" string
10316    | RConstOptString _ -> pr "Maybe %s" string
10317    | RString _ -> pr "%s" string
10318    | RStringList _ -> pr "[%s]" string
10319    | RStruct (_, typ) ->
10320        let name = java_name_of_struct typ in
10321        pr "%s" name
10322    | RStructList (_, typ) ->
10323        let name = java_name_of_struct typ in
10324        pr "[%s]" name
10325    | RHashtable _ -> pr "Hashtable"
10326    | RBufferOut _ -> pr "%s" string
10327   );
10328   pr ")"
10329
10330 and generate_csharp () =
10331   generate_header CPlusPlusStyle LGPLv2plus;
10332
10333   (* XXX Make this configurable by the C# assembly users. *)
10334   let library = "libguestfs.so.0" in
10335
10336   pr "\
10337 // These C# bindings are highly experimental at present.
10338 //
10339 // Firstly they only work on Linux (ie. Mono).  In order to get them
10340 // to work on Windows (ie. .Net) you would need to port the library
10341 // itself to Windows first.
10342 //
10343 // The second issue is that some calls are known to be incorrect and
10344 // can cause Mono to segfault.  Particularly: calls which pass or
10345 // return string[], or return any structure value.  This is because
10346 // we haven't worked out the correct way to do this from C#.
10347 //
10348 // The third issue is that when compiling you get a lot of warnings.
10349 // We are not sure whether the warnings are important or not.
10350 //
10351 // Fourthly we do not routinely build or test these bindings as part
10352 // of the make && make check cycle, which means that regressions might
10353 // go unnoticed.
10354 //
10355 // Suggestions and patches are welcome.
10356
10357 // To compile:
10358 //
10359 // gmcs Libguestfs.cs
10360 // mono Libguestfs.exe
10361 //
10362 // (You'll probably want to add a Test class / static main function
10363 // otherwise this won't do anything useful).
10364
10365 using System;
10366 using System.IO;
10367 using System.Runtime.InteropServices;
10368 using System.Runtime.Serialization;
10369 using System.Collections;
10370
10371 namespace Guestfs
10372 {
10373   class Error : System.ApplicationException
10374   {
10375     public Error (string message) : base (message) {}
10376     protected Error (SerializationInfo info, StreamingContext context) {}
10377   }
10378
10379   class Guestfs
10380   {
10381     IntPtr _handle;
10382
10383     [DllImport (\"%s\")]
10384     static extern IntPtr guestfs_create ();
10385
10386     public Guestfs ()
10387     {
10388       _handle = guestfs_create ();
10389       if (_handle == IntPtr.Zero)
10390         throw new Error (\"could not create guestfs handle\");
10391     }
10392
10393     [DllImport (\"%s\")]
10394     static extern void guestfs_close (IntPtr h);
10395
10396     ~Guestfs ()
10397     {
10398       guestfs_close (_handle);
10399     }
10400
10401     [DllImport (\"%s\")]
10402     static extern string guestfs_last_error (IntPtr h);
10403
10404 " library library library;
10405
10406   (* Generate C# structure bindings.  We prefix struct names with
10407    * underscore because C# cannot have conflicting struct names and
10408    * method names (eg. "class stat" and "stat").
10409    *)
10410   List.iter (
10411     fun (typ, cols) ->
10412       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10413       pr "    public class _%s {\n" typ;
10414       List.iter (
10415         function
10416         | name, FChar -> pr "      char %s;\n" name
10417         | name, FString -> pr "      string %s;\n" name
10418         | name, FBuffer ->
10419             pr "      uint %s_len;\n" name;
10420             pr "      string %s;\n" name
10421         | name, FUUID ->
10422             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10423             pr "      string %s;\n" name
10424         | name, FUInt32 -> pr "      uint %s;\n" name
10425         | name, FInt32 -> pr "      int %s;\n" name
10426         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10427         | name, FInt64 -> pr "      long %s;\n" name
10428         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10429       ) cols;
10430       pr "    }\n";
10431       pr "\n"
10432   ) structs;
10433
10434   (* Generate C# function bindings. *)
10435   List.iter (
10436     fun (name, style, _, _, _, shortdesc, _) ->
10437       let rec csharp_return_type () =
10438         match fst style with
10439         | RErr -> "void"
10440         | RBool n -> "bool"
10441         | RInt n -> "int"
10442         | RInt64 n -> "long"
10443         | RConstString n
10444         | RConstOptString n
10445         | RString n
10446         | RBufferOut n -> "string"
10447         | RStruct (_,n) -> "_" ^ n
10448         | RHashtable n -> "Hashtable"
10449         | RStringList n -> "string[]"
10450         | RStructList (_,n) -> sprintf "_%s[]" n
10451
10452       and c_return_type () =
10453         match fst style with
10454         | RErr
10455         | RBool _
10456         | RInt _ -> "int"
10457         | RInt64 _ -> "long"
10458         | RConstString _
10459         | RConstOptString _
10460         | RString _
10461         | RBufferOut _ -> "string"
10462         | RStruct (_,n) -> "_" ^ n
10463         | RHashtable _
10464         | RStringList _ -> "string[]"
10465         | RStructList (_,n) -> sprintf "_%s[]" n
10466
10467       and c_error_comparison () =
10468         match fst style with
10469         | RErr
10470         | RBool _
10471         | RInt _
10472         | RInt64 _ -> "== -1"
10473         | RConstString _
10474         | RConstOptString _
10475         | RString _
10476         | RBufferOut _
10477         | RStruct (_,_)
10478         | RHashtable _
10479         | RStringList _
10480         | RStructList (_,_) -> "== null"
10481
10482       and generate_extern_prototype () =
10483         pr "    static extern %s guestfs_%s (IntPtr h"
10484           (c_return_type ()) name;
10485         List.iter (
10486           function
10487           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10488           | FileIn n | FileOut n ->
10489               pr ", [In] string %s" n
10490           | StringList n | DeviceList n ->
10491               pr ", [In] string[] %s" n
10492           | Bool n ->
10493               pr ", bool %s" n
10494           | Int n ->
10495               pr ", int %s" n
10496           | Int64 n ->
10497               pr ", long %s" n
10498         ) (snd style);
10499         pr ");\n"
10500
10501       and generate_public_prototype () =
10502         pr "    public %s %s (" (csharp_return_type ()) name;
10503         let comma = ref false in
10504         let next () =
10505           if !comma then pr ", ";
10506           comma := true
10507         in
10508         List.iter (
10509           function
10510           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10511           | FileIn n | FileOut n ->
10512               next (); pr "string %s" n
10513           | StringList n | DeviceList n ->
10514               next (); pr "string[] %s" n
10515           | Bool n ->
10516               next (); pr "bool %s" n
10517           | Int n ->
10518               next (); pr "int %s" n
10519           | Int64 n ->
10520               next (); pr "long %s" n
10521         ) (snd style);
10522         pr ")\n"
10523
10524       and generate_call () =
10525         pr "guestfs_%s (_handle" name;
10526         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10527         pr ");\n";
10528       in
10529
10530       pr "    [DllImport (\"%s\")]\n" library;
10531       generate_extern_prototype ();
10532       pr "\n";
10533       pr "    /// <summary>\n";
10534       pr "    /// %s\n" shortdesc;
10535       pr "    /// </summary>\n";
10536       generate_public_prototype ();
10537       pr "    {\n";
10538       pr "      %s r;\n" (c_return_type ());
10539       pr "      r = ";
10540       generate_call ();
10541       pr "      if (r %s)\n" (c_error_comparison ());
10542       pr "        throw new Error (guestfs_last_error (_handle));\n";
10543       (match fst style with
10544        | RErr -> ()
10545        | RBool _ ->
10546            pr "      return r != 0 ? true : false;\n"
10547        | RHashtable _ ->
10548            pr "      Hashtable rr = new Hashtable ();\n";
10549            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10550            pr "        rr.Add (r[i], r[i+1]);\n";
10551            pr "      return rr;\n"
10552        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10553        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10554        | RStructList _ ->
10555            pr "      return r;\n"
10556       );
10557       pr "    }\n";
10558       pr "\n";
10559   ) all_functions_sorted;
10560
10561   pr "  }
10562 }
10563 "
10564
10565 and generate_bindtests () =
10566   generate_header CStyle LGPLv2plus;
10567
10568   pr "\
10569 #include <stdio.h>
10570 #include <stdlib.h>
10571 #include <inttypes.h>
10572 #include <string.h>
10573
10574 #include \"guestfs.h\"
10575 #include \"guestfs-internal.h\"
10576 #include \"guestfs-internal-actions.h\"
10577 #include \"guestfs_protocol.h\"
10578
10579 #define error guestfs_error
10580 #define safe_calloc guestfs_safe_calloc
10581 #define safe_malloc guestfs_safe_malloc
10582
10583 static void
10584 print_strings (char *const *argv)
10585 {
10586   int argc;
10587
10588   printf (\"[\");
10589   for (argc = 0; argv[argc] != NULL; ++argc) {
10590     if (argc > 0) printf (\", \");
10591     printf (\"\\\"%%s\\\"\", argv[argc]);
10592   }
10593   printf (\"]\\n\");
10594 }
10595
10596 /* The test0 function prints its parameters to stdout. */
10597 ";
10598
10599   let test0, tests =
10600     match test_functions with
10601     | [] -> assert false
10602     | test0 :: tests -> test0, tests in
10603
10604   let () =
10605     let (name, style, _, _, _, _, _) = test0 in
10606     generate_prototype ~extern:false ~semicolon:false ~newline:true
10607       ~handle:"g" ~prefix:"guestfs__" name style;
10608     pr "{\n";
10609     List.iter (
10610       function
10611       | Pathname n
10612       | Device n | Dev_or_Path n
10613       | String n
10614       | FileIn n
10615       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10616       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10617       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10618       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10619       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10620       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10621     ) (snd style);
10622     pr "  /* Java changes stdout line buffering so we need this: */\n";
10623     pr "  fflush (stdout);\n";
10624     pr "  return 0;\n";
10625     pr "}\n";
10626     pr "\n" in
10627
10628   List.iter (
10629     fun (name, style, _, _, _, _, _) ->
10630       if String.sub name (String.length name - 3) 3 <> "err" then (
10631         pr "/* Test normal return. */\n";
10632         generate_prototype ~extern:false ~semicolon:false ~newline:true
10633           ~handle:"g" ~prefix:"guestfs__" name style;
10634         pr "{\n";
10635         (match fst style with
10636          | RErr ->
10637              pr "  return 0;\n"
10638          | RInt _ ->
10639              pr "  int r;\n";
10640              pr "  sscanf (val, \"%%d\", &r);\n";
10641              pr "  return r;\n"
10642          | RInt64 _ ->
10643              pr "  int64_t r;\n";
10644              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10645              pr "  return r;\n"
10646          | RBool _ ->
10647              pr "  return STREQ (val, \"true\");\n"
10648          | RConstString _
10649          | RConstOptString _ ->
10650              (* Can't return the input string here.  Return a static
10651               * string so we ensure we get a segfault if the caller
10652               * tries to free it.
10653               *)
10654              pr "  return \"static string\";\n"
10655          | RString _ ->
10656              pr "  return strdup (val);\n"
10657          | RStringList _ ->
10658              pr "  char **strs;\n";
10659              pr "  int n, i;\n";
10660              pr "  sscanf (val, \"%%d\", &n);\n";
10661              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10662              pr "  for (i = 0; i < n; ++i) {\n";
10663              pr "    strs[i] = safe_malloc (g, 16);\n";
10664              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10665              pr "  }\n";
10666              pr "  strs[n] = NULL;\n";
10667              pr "  return strs;\n"
10668          | RStruct (_, typ) ->
10669              pr "  struct guestfs_%s *r;\n" typ;
10670              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10671              pr "  return r;\n"
10672          | RStructList (_, typ) ->
10673              pr "  struct guestfs_%s_list *r;\n" typ;
10674              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10675              pr "  sscanf (val, \"%%d\", &r->len);\n";
10676              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10677              pr "  return r;\n"
10678          | RHashtable _ ->
10679              pr "  char **strs;\n";
10680              pr "  int n, i;\n";
10681              pr "  sscanf (val, \"%%d\", &n);\n";
10682              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10683              pr "  for (i = 0; i < n; ++i) {\n";
10684              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10685              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10686              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10687              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10688              pr "  }\n";
10689              pr "  strs[n*2] = NULL;\n";
10690              pr "  return strs;\n"
10691          | RBufferOut _ ->
10692              pr "  return strdup (val);\n"
10693         );
10694         pr "}\n";
10695         pr "\n"
10696       ) else (
10697         pr "/* Test error return. */\n";
10698         generate_prototype ~extern:false ~semicolon:false ~newline:true
10699           ~handle:"g" ~prefix:"guestfs__" name style;
10700         pr "{\n";
10701         pr "  error (g, \"error\");\n";
10702         (match fst style with
10703          | RErr | RInt _ | RInt64 _ | RBool _ ->
10704              pr "  return -1;\n"
10705          | RConstString _ | RConstOptString _
10706          | RString _ | RStringList _ | RStruct _
10707          | RStructList _
10708          | RHashtable _
10709          | RBufferOut _ ->
10710              pr "  return NULL;\n"
10711         );
10712         pr "}\n";
10713         pr "\n"
10714       )
10715   ) tests
10716
10717 and generate_ocaml_bindtests () =
10718   generate_header OCamlStyle GPLv2plus;
10719
10720   pr "\
10721 let () =
10722   let g = Guestfs.create () in
10723 ";
10724
10725   let mkargs args =
10726     String.concat " " (
10727       List.map (
10728         function
10729         | CallString s -> "\"" ^ s ^ "\""
10730         | CallOptString None -> "None"
10731         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10732         | CallStringList xs ->
10733             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10734         | CallInt i when i >= 0 -> string_of_int i
10735         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10736         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10737         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10738         | CallBool b -> string_of_bool b
10739       ) args
10740     )
10741   in
10742
10743   generate_lang_bindtests (
10744     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10745   );
10746
10747   pr "print_endline \"EOF\"\n"
10748
10749 and generate_perl_bindtests () =
10750   pr "#!/usr/bin/perl -w\n";
10751   generate_header HashStyle GPLv2plus;
10752
10753   pr "\
10754 use strict;
10755
10756 use Sys::Guestfs;
10757
10758 my $g = Sys::Guestfs->new ();
10759 ";
10760
10761   let mkargs args =
10762     String.concat ", " (
10763       List.map (
10764         function
10765         | CallString s -> "\"" ^ s ^ "\""
10766         | CallOptString None -> "undef"
10767         | CallOptString (Some s) -> sprintf "\"%s\"" s
10768         | CallStringList xs ->
10769             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10770         | CallInt i -> string_of_int i
10771         | CallInt64 i -> Int64.to_string i
10772         | CallBool b -> if b then "1" else "0"
10773       ) args
10774     )
10775   in
10776
10777   generate_lang_bindtests (
10778     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10779   );
10780
10781   pr "print \"EOF\\n\"\n"
10782
10783 and generate_python_bindtests () =
10784   generate_header HashStyle GPLv2plus;
10785
10786   pr "\
10787 import guestfs
10788
10789 g = guestfs.GuestFS ()
10790 ";
10791
10792   let mkargs args =
10793     String.concat ", " (
10794       List.map (
10795         function
10796         | CallString s -> "\"" ^ s ^ "\""
10797         | CallOptString None -> "None"
10798         | CallOptString (Some s) -> sprintf "\"%s\"" s
10799         | CallStringList xs ->
10800             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10801         | CallInt i -> string_of_int i
10802         | CallInt64 i -> Int64.to_string i
10803         | CallBool b -> if b then "1" else "0"
10804       ) args
10805     )
10806   in
10807
10808   generate_lang_bindtests (
10809     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10810   );
10811
10812   pr "print \"EOF\"\n"
10813
10814 and generate_ruby_bindtests () =
10815   generate_header HashStyle GPLv2plus;
10816
10817   pr "\
10818 require 'guestfs'
10819
10820 g = Guestfs::create()
10821 ";
10822
10823   let mkargs args =
10824     String.concat ", " (
10825       List.map (
10826         function
10827         | CallString s -> "\"" ^ s ^ "\""
10828         | CallOptString None -> "nil"
10829         | CallOptString (Some s) -> sprintf "\"%s\"" s
10830         | CallStringList xs ->
10831             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10832         | CallInt i -> string_of_int i
10833         | CallInt64 i -> Int64.to_string i
10834         | CallBool b -> string_of_bool b
10835       ) args
10836     )
10837   in
10838
10839   generate_lang_bindtests (
10840     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10841   );
10842
10843   pr "print \"EOF\\n\"\n"
10844
10845 and generate_java_bindtests () =
10846   generate_header CStyle GPLv2plus;
10847
10848   pr "\
10849 import com.redhat.et.libguestfs.*;
10850
10851 public class Bindtests {
10852     public static void main (String[] argv)
10853     {
10854         try {
10855             GuestFS g = new GuestFS ();
10856 ";
10857
10858   let mkargs args =
10859     String.concat ", " (
10860       List.map (
10861         function
10862         | CallString s -> "\"" ^ s ^ "\""
10863         | CallOptString None -> "null"
10864         | CallOptString (Some s) -> sprintf "\"%s\"" s
10865         | CallStringList xs ->
10866             "new String[]{" ^
10867               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10868         | CallInt i -> string_of_int i
10869         | CallInt64 i -> Int64.to_string i
10870         | CallBool b -> string_of_bool b
10871       ) args
10872     )
10873   in
10874
10875   generate_lang_bindtests (
10876     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10877   );
10878
10879   pr "
10880             System.out.println (\"EOF\");
10881         }
10882         catch (Exception exn) {
10883             System.err.println (exn);
10884             System.exit (1);
10885         }
10886     }
10887 }
10888 "
10889
10890 and generate_haskell_bindtests () =
10891   generate_header HaskellStyle GPLv2plus;
10892
10893   pr "\
10894 module Bindtests where
10895 import qualified Guestfs
10896
10897 main = do
10898   g <- Guestfs.create
10899 ";
10900
10901   let mkargs args =
10902     String.concat " " (
10903       List.map (
10904         function
10905         | CallString s -> "\"" ^ s ^ "\""
10906         | CallOptString None -> "Nothing"
10907         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10908         | CallStringList xs ->
10909             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10910         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10911         | CallInt i -> string_of_int i
10912         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10913         | CallInt64 i -> Int64.to_string i
10914         | CallBool true -> "True"
10915         | CallBool false -> "False"
10916       ) args
10917     )
10918   in
10919
10920   generate_lang_bindtests (
10921     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10922   );
10923
10924   pr "  putStrLn \"EOF\"\n"
10925
10926 (* Language-independent bindings tests - we do it this way to
10927  * ensure there is parity in testing bindings across all languages.
10928  *)
10929 and generate_lang_bindtests call =
10930   call "test0" [CallString "abc"; CallOptString (Some "def");
10931                 CallStringList []; CallBool false;
10932                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10933   call "test0" [CallString "abc"; CallOptString None;
10934                 CallStringList []; CallBool false;
10935                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10936   call "test0" [CallString ""; CallOptString (Some "def");
10937                 CallStringList []; CallBool false;
10938                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10939   call "test0" [CallString ""; CallOptString (Some "");
10940                 CallStringList []; CallBool false;
10941                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10942   call "test0" [CallString "abc"; CallOptString (Some "def");
10943                 CallStringList ["1"]; CallBool false;
10944                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10945   call "test0" [CallString "abc"; CallOptString (Some "def");
10946                 CallStringList ["1"; "2"]; CallBool false;
10947                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10948   call "test0" [CallString "abc"; CallOptString (Some "def");
10949                 CallStringList ["1"]; CallBool true;
10950                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10951   call "test0" [CallString "abc"; CallOptString (Some "def");
10952                 CallStringList ["1"]; CallBool false;
10953                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10954   call "test0" [CallString "abc"; CallOptString (Some "def");
10955                 CallStringList ["1"]; CallBool false;
10956                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10957   call "test0" [CallString "abc"; CallOptString (Some "def");
10958                 CallStringList ["1"]; CallBool false;
10959                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10960   call "test0" [CallString "abc"; CallOptString (Some "def");
10961                 CallStringList ["1"]; CallBool false;
10962                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10963   call "test0" [CallString "abc"; CallOptString (Some "def");
10964                 CallStringList ["1"]; CallBool false;
10965                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10966   call "test0" [CallString "abc"; CallOptString (Some "def");
10967                 CallStringList ["1"]; CallBool false;
10968                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10969
10970 (* XXX Add here tests of the return and error functions. *)
10971
10972 (* Code to generator bindings for virt-inspector.  Currently only
10973  * implemented for OCaml code (for virt-p2v 2.0).
10974  *)
10975 let rng_input = "inspector/virt-inspector.rng"
10976
10977 (* Read the input file and parse it into internal structures.  This is
10978  * by no means a complete RELAX NG parser, but is just enough to be
10979  * able to parse the specific input file.
10980  *)
10981 type rng =
10982   | Element of string * rng list        (* <element name=name/> *)
10983   | Attribute of string * rng list        (* <attribute name=name/> *)
10984   | Interleave of rng list                (* <interleave/> *)
10985   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10986   | OneOrMore of rng                        (* <oneOrMore/> *)
10987   | Optional of rng                        (* <optional/> *)
10988   | Choice of string list                (* <choice><value/>*</choice> *)
10989   | Value of string                        (* <value>str</value> *)
10990   | Text                                (* <text/> *)
10991
10992 let rec string_of_rng = function
10993   | Element (name, xs) ->
10994       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10995   | Attribute (name, xs) ->
10996       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10997   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10998   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10999   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11000   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11001   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11002   | Value value -> "Value \"" ^ value ^ "\""
11003   | Text -> "Text"
11004
11005 and string_of_rng_list xs =
11006   String.concat ", " (List.map string_of_rng xs)
11007
11008 let rec parse_rng ?defines context = function
11009   | [] -> []
11010   | Xml.Element ("element", ["name", name], children) :: rest ->
11011       Element (name, parse_rng ?defines context children)
11012       :: parse_rng ?defines context rest
11013   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11014       Attribute (name, parse_rng ?defines context children)
11015       :: parse_rng ?defines context rest
11016   | Xml.Element ("interleave", [], children) :: rest ->
11017       Interleave (parse_rng ?defines context children)
11018       :: parse_rng ?defines context rest
11019   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11020       let rng = parse_rng ?defines context [child] in
11021       (match rng with
11022        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11023        | _ ->
11024            failwithf "%s: <zeroOrMore> contains more than one child element"
11025              context
11026       )
11027   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11028       let rng = parse_rng ?defines context [child] in
11029       (match rng with
11030        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11031        | _ ->
11032            failwithf "%s: <oneOrMore> contains more than one child element"
11033              context
11034       )
11035   | Xml.Element ("optional", [], [child]) :: rest ->
11036       let rng = parse_rng ?defines context [child] in
11037       (match rng with
11038        | [child] -> Optional child :: parse_rng ?defines context rest
11039        | _ ->
11040            failwithf "%s: <optional> contains more than one child element"
11041              context
11042       )
11043   | Xml.Element ("choice", [], children) :: rest ->
11044       let values = List.map (
11045         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11046         | _ ->
11047             failwithf "%s: can't handle anything except <value> in <choice>"
11048               context
11049       ) children in
11050       Choice values
11051       :: parse_rng ?defines context rest
11052   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11053       Value value :: parse_rng ?defines context rest
11054   | Xml.Element ("text", [], []) :: rest ->
11055       Text :: parse_rng ?defines context rest
11056   | Xml.Element ("ref", ["name", name], []) :: rest ->
11057       (* Look up the reference.  Because of limitations in this parser,
11058        * we can't handle arbitrarily nested <ref> yet.  You can only
11059        * use <ref> from inside <start>.
11060        *)
11061       (match defines with
11062        | None ->
11063            failwithf "%s: contains <ref>, but no refs are defined yet" context
11064        | Some map ->
11065            let rng = StringMap.find name map in
11066            rng @ parse_rng ?defines context rest
11067       )
11068   | x :: _ ->
11069       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11070
11071 let grammar =
11072   let xml = Xml.parse_file rng_input in
11073   match xml with
11074   | Xml.Element ("grammar", _,
11075                  Xml.Element ("start", _, gram) :: defines) ->
11076       (* The <define/> elements are referenced in the <start> section,
11077        * so build a map of those first.
11078        *)
11079       let defines = List.fold_left (
11080         fun map ->
11081           function Xml.Element ("define", ["name", name], defn) ->
11082             StringMap.add name defn map
11083           | _ ->
11084               failwithf "%s: expected <define name=name/>" rng_input
11085       ) StringMap.empty defines in
11086       let defines = StringMap.mapi parse_rng defines in
11087
11088       (* Parse the <start> clause, passing the defines. *)
11089       parse_rng ~defines "<start>" gram
11090   | _ ->
11091       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11092         rng_input
11093
11094 let name_of_field = function
11095   | Element (name, _) | Attribute (name, _)
11096   | ZeroOrMore (Element (name, _))
11097   | OneOrMore (Element (name, _))
11098   | Optional (Element (name, _)) -> name
11099   | Optional (Attribute (name, _)) -> name
11100   | Text -> (* an unnamed field in an element *)
11101       "data"
11102   | rng ->
11103       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11104
11105 (* At the moment this function only generates OCaml types.  However we
11106  * should parameterize it later so it can generate types/structs in a
11107  * variety of languages.
11108  *)
11109 let generate_types xs =
11110   (* A simple type is one that can be printed out directly, eg.
11111    * "string option".  A complex type is one which has a name and has
11112    * to be defined via another toplevel definition, eg. a struct.
11113    *
11114    * generate_type generates code for either simple or complex types.
11115    * In the simple case, it returns the string ("string option").  In
11116    * the complex case, it returns the name ("mountpoint").  In the
11117    * complex case it has to print out the definition before returning,
11118    * so it should only be called when we are at the beginning of a
11119    * new line (BOL context).
11120    *)
11121   let rec generate_type = function
11122     | Text ->                                (* string *)
11123         "string", true
11124     | Choice values ->                        (* [`val1|`val2|...] *)
11125         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11126     | ZeroOrMore rng ->                        (* <rng> list *)
11127         let t, is_simple = generate_type rng in
11128         t ^ " list (* 0 or more *)", is_simple
11129     | OneOrMore rng ->                        (* <rng> list *)
11130         let t, is_simple = generate_type rng in
11131         t ^ " list (* 1 or more *)", is_simple
11132                                         (* virt-inspector hack: bool *)
11133     | Optional (Attribute (name, [Value "1"])) ->
11134         "bool", true
11135     | Optional rng ->                        (* <rng> list *)
11136         let t, is_simple = generate_type rng in
11137         t ^ " option", is_simple
11138                                         (* type name = { fields ... } *)
11139     | Element (name, fields) when is_attrs_interleave fields ->
11140         generate_type_struct name (get_attrs_interleave fields)
11141     | Element (name, [field])                (* type name = field *)
11142     | Attribute (name, [field]) ->
11143         let t, is_simple = generate_type field in
11144         if is_simple then (t, true)
11145         else (
11146           pr "type %s = %s\n" name t;
11147           name, false
11148         )
11149     | Element (name, fields) ->              (* type name = { fields ... } *)
11150         generate_type_struct name fields
11151     | rng ->
11152         failwithf "generate_type failed at: %s" (string_of_rng rng)
11153
11154   and is_attrs_interleave = function
11155     | [Interleave _] -> true
11156     | Attribute _ :: fields -> is_attrs_interleave fields
11157     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11158     | _ -> false
11159
11160   and get_attrs_interleave = function
11161     | [Interleave fields] -> fields
11162     | ((Attribute _) as field) :: fields
11163     | ((Optional (Attribute _)) as field) :: fields ->
11164         field :: get_attrs_interleave fields
11165     | _ -> assert false
11166
11167   and generate_types xs =
11168     List.iter (fun x -> ignore (generate_type x)) xs
11169
11170   and generate_type_struct name fields =
11171     (* Calculate the types of the fields first.  We have to do this
11172      * before printing anything so we are still in BOL context.
11173      *)
11174     let types = List.map fst (List.map generate_type fields) in
11175
11176     (* Special case of a struct containing just a string and another
11177      * field.  Turn it into an assoc list.
11178      *)
11179     match types with
11180     | ["string"; other] ->
11181         let fname1, fname2 =
11182           match fields with
11183           | [f1; f2] -> name_of_field f1, name_of_field f2
11184           | _ -> assert false in
11185         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11186         name, false
11187
11188     | types ->
11189         pr "type %s = {\n" name;
11190         List.iter (
11191           fun (field, ftype) ->
11192             let fname = name_of_field field in
11193             pr "  %s_%s : %s;\n" name fname ftype
11194         ) (List.combine fields types);
11195         pr "}\n";
11196         (* Return the name of this type, and
11197          * false because it's not a simple type.
11198          *)
11199         name, false
11200   in
11201
11202   generate_types xs
11203
11204 let generate_parsers xs =
11205   (* As for generate_type above, generate_parser makes a parser for
11206    * some type, and returns the name of the parser it has generated.
11207    * Because it (may) need to print something, it should always be
11208    * called in BOL context.
11209    *)
11210   let rec generate_parser = function
11211     | Text ->                                (* string *)
11212         "string_child_or_empty"
11213     | Choice values ->                        (* [`val1|`val2|...] *)
11214         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11215           (String.concat "|"
11216              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11217     | ZeroOrMore rng ->                        (* <rng> list *)
11218         let pa = generate_parser rng in
11219         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11220     | OneOrMore rng ->                        (* <rng> list *)
11221         let pa = generate_parser rng in
11222         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11223                                         (* virt-inspector hack: bool *)
11224     | Optional (Attribute (name, [Value "1"])) ->
11225         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11226     | Optional rng ->                        (* <rng> list *)
11227         let pa = generate_parser rng in
11228         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11229                                         (* type name = { fields ... } *)
11230     | Element (name, fields) when is_attrs_interleave fields ->
11231         generate_parser_struct name (get_attrs_interleave fields)
11232     | Element (name, [field]) ->        (* type name = field *)
11233         let pa = generate_parser field in
11234         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11235         pr "let %s =\n" parser_name;
11236         pr "  %s\n" pa;
11237         pr "let parse_%s = %s\n" name parser_name;
11238         parser_name
11239     | Attribute (name, [field]) ->
11240         let pa = generate_parser field in
11241         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11242         pr "let %s =\n" parser_name;
11243         pr "  %s\n" pa;
11244         pr "let parse_%s = %s\n" name parser_name;
11245         parser_name
11246     | Element (name, fields) ->              (* type name = { fields ... } *)
11247         generate_parser_struct name ([], fields)
11248     | rng ->
11249         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11250
11251   and is_attrs_interleave = function
11252     | [Interleave _] -> true
11253     | Attribute _ :: fields -> is_attrs_interleave fields
11254     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11255     | _ -> false
11256
11257   and get_attrs_interleave = function
11258     | [Interleave fields] -> [], fields
11259     | ((Attribute _) as field) :: fields
11260     | ((Optional (Attribute _)) as field) :: fields ->
11261         let attrs, interleaves = get_attrs_interleave fields in
11262         (field :: attrs), interleaves
11263     | _ -> assert false
11264
11265   and generate_parsers xs =
11266     List.iter (fun x -> ignore (generate_parser x)) xs
11267
11268   and generate_parser_struct name (attrs, interleaves) =
11269     (* Generate parsers for the fields first.  We have to do this
11270      * before printing anything so we are still in BOL context.
11271      *)
11272     let fields = attrs @ interleaves in
11273     let pas = List.map generate_parser fields in
11274
11275     (* Generate an intermediate tuple from all the fields first.
11276      * If the type is just a string + another field, then we will
11277      * return this directly, otherwise it is turned into a record.
11278      *
11279      * RELAX NG note: This code treats <interleave> and plain lists of
11280      * fields the same.  In other words, it doesn't bother enforcing
11281      * any ordering of fields in the XML.
11282      *)
11283     pr "let parse_%s x =\n" name;
11284     pr "  let t = (\n    ";
11285     let comma = ref false in
11286     List.iter (
11287       fun x ->
11288         if !comma then pr ",\n    ";
11289         comma := true;
11290         match x with
11291         | Optional (Attribute (fname, [field])), pa ->
11292             pr "%s x" pa
11293         | Optional (Element (fname, [field])), pa ->
11294             pr "%s (optional_child %S x)" pa fname
11295         | Attribute (fname, [Text]), _ ->
11296             pr "attribute %S x" fname
11297         | (ZeroOrMore _ | OneOrMore _), pa ->
11298             pr "%s x" pa
11299         | Text, pa ->
11300             pr "%s x" pa
11301         | (field, pa) ->
11302             let fname = name_of_field field in
11303             pr "%s (child %S x)" pa fname
11304     ) (List.combine fields pas);
11305     pr "\n  ) in\n";
11306
11307     (match fields with
11308      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11309          pr "  t\n"
11310
11311      | _ ->
11312          pr "  (Obj.magic t : %s)\n" name
11313 (*
11314          List.iter (
11315            function
11316            | (Optional (Attribute (fname, [field])), pa) ->
11317                pr "  %s_%s =\n" name fname;
11318                pr "    %s x;\n" pa
11319            | (Optional (Element (fname, [field])), pa) ->
11320                pr "  %s_%s =\n" name fname;
11321                pr "    (let x = optional_child %S x in\n" fname;
11322                pr "     %s x);\n" pa
11323            | (field, pa) ->
11324                let fname = name_of_field field in
11325                pr "  %s_%s =\n" name fname;
11326                pr "    (let x = child %S x in\n" fname;
11327                pr "     %s x);\n" pa
11328          ) (List.combine fields pas);
11329          pr "}\n"
11330 *)
11331     );
11332     sprintf "parse_%s" name
11333   in
11334
11335   generate_parsers xs
11336
11337 (* Generate ocaml/guestfs_inspector.mli. *)
11338 let generate_ocaml_inspector_mli () =
11339   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11340
11341   pr "\
11342 (** This is an OCaml language binding to the external [virt-inspector]
11343     program.
11344
11345     For more information, please read the man page [virt-inspector(1)].
11346 *)
11347
11348 ";
11349
11350   generate_types grammar;
11351   pr "(** The nested information returned from the {!inspect} function. *)\n";
11352   pr "\n";
11353
11354   pr "\
11355 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11356 (** To inspect a libvirt domain called [name], pass a singleton
11357     list: [inspect [name]].  When using libvirt only, you may
11358     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11359
11360     To inspect a disk image or images, pass a list of the filenames
11361     of the disk images: [inspect filenames]
11362
11363     This function inspects the given guest or disk images and
11364     returns a list of operating system(s) found and a large amount
11365     of information about them.  In the vast majority of cases,
11366     a virtual machine only contains a single operating system.
11367
11368     If the optional [~xml] parameter is given, then this function
11369     skips running the external virt-inspector program and just
11370     parses the given XML directly (which is expected to be XML
11371     produced from a previous run of virt-inspector).  The list of
11372     names and connect URI are ignored in this case.
11373
11374     This function can throw a wide variety of exceptions, for example
11375     if the external virt-inspector program cannot be found, or if
11376     it doesn't generate valid XML.
11377 *)
11378 "
11379
11380 (* Generate ocaml/guestfs_inspector.ml. *)
11381 let generate_ocaml_inspector_ml () =
11382   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11383
11384   pr "open Unix\n";
11385   pr "\n";
11386
11387   generate_types grammar;
11388   pr "\n";
11389
11390   pr "\
11391 (* Misc functions which are used by the parser code below. *)
11392 let first_child = function
11393   | Xml.Element (_, _, c::_) -> c
11394   | Xml.Element (name, _, []) ->
11395       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11396   | Xml.PCData str ->
11397       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11398
11399 let string_child_or_empty = function
11400   | Xml.Element (_, _, [Xml.PCData s]) -> s
11401   | Xml.Element (_, _, []) -> \"\"
11402   | Xml.Element (x, _, _) ->
11403       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11404                 x ^ \" instead\")
11405   | Xml.PCData str ->
11406       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11407
11408 let optional_child name xml =
11409   let children = Xml.children xml in
11410   try
11411     Some (List.find (function
11412                      | Xml.Element (n, _, _) when n = name -> true
11413                      | _ -> false) children)
11414   with
11415     Not_found -> None
11416
11417 let child name xml =
11418   match optional_child name xml with
11419   | Some c -> c
11420   | None ->
11421       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11422
11423 let attribute name xml =
11424   try Xml.attrib xml name
11425   with Xml.No_attribute _ ->
11426     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11427
11428 ";
11429
11430   generate_parsers grammar;
11431   pr "\n";
11432
11433   pr "\
11434 (* Run external virt-inspector, then use parser to parse the XML. *)
11435 let inspect ?connect ?xml names =
11436   let xml =
11437     match xml with
11438     | None ->
11439         if names = [] then invalid_arg \"inspect: no names given\";
11440         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11441           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11442           names in
11443         let cmd = List.map Filename.quote cmd in
11444         let cmd = String.concat \" \" cmd in
11445         let chan = open_process_in cmd in
11446         let xml = Xml.parse_in chan in
11447         (match close_process_in chan with
11448          | WEXITED 0 -> ()
11449          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11450          | WSIGNALED i | WSTOPPED i ->
11451              failwith (\"external virt-inspector command died or stopped on sig \" ^
11452                        string_of_int i)
11453         );
11454         xml
11455     | Some doc ->
11456         Xml.parse_string doc in
11457   parse_operatingsystems xml
11458 "
11459
11460 (* This is used to generate the src/MAX_PROC_NR file which
11461  * contains the maximum procedure number, a surrogate for the
11462  * ABI version number.  See src/Makefile.am for the details.
11463  *)
11464 and generate_max_proc_nr () =
11465   let proc_nrs = List.map (
11466     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11467   ) daemon_functions in
11468
11469   let max_proc_nr = List.fold_left max 0 proc_nrs in
11470
11471   pr "%d\n" max_proc_nr
11472
11473 let output_to filename k =
11474   let filename_new = filename ^ ".new" in
11475   chan := open_out filename_new;
11476   k ();
11477   close_out !chan;
11478   chan := Pervasives.stdout;
11479
11480   (* Is the new file different from the current file? *)
11481   if Sys.file_exists filename && files_equal filename filename_new then
11482     unlink filename_new                 (* same, so skip it *)
11483   else (
11484     (* different, overwrite old one *)
11485     (try chmod filename 0o644 with Unix_error _ -> ());
11486     rename filename_new filename;
11487     chmod filename 0o444;
11488     printf "written %s\n%!" filename;
11489   )
11490
11491 let perror msg = function
11492   | Unix_error (err, _, _) ->
11493       eprintf "%s: %s\n" msg (error_message err)
11494   | exn ->
11495       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11496
11497 (* Main program. *)
11498 let () =
11499   let lock_fd =
11500     try openfile "HACKING" [O_RDWR] 0
11501     with
11502     | Unix_error (ENOENT, _, _) ->
11503         eprintf "\
11504 You are probably running this from the wrong directory.
11505 Run it from the top source directory using the command
11506   src/generator.ml
11507 ";
11508         exit 1
11509     | exn ->
11510         perror "open: HACKING" exn;
11511         exit 1 in
11512
11513   (* Acquire a lock so parallel builds won't try to run the generator
11514    * twice at the same time.  Subsequent builds will wait for the first
11515    * one to finish.  Note the lock is released implicitly when the
11516    * program exits.
11517    *)
11518   (try lockf lock_fd F_LOCK 1
11519    with exn ->
11520      perror "lock: HACKING" exn;
11521      exit 1);
11522
11523   check_functions ();
11524
11525   output_to "src/guestfs_protocol.x" generate_xdr;
11526   output_to "src/guestfs-structs.h" generate_structs_h;
11527   output_to "src/guestfs-actions.h" generate_actions_h;
11528   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11529   output_to "src/guestfs-actions.c" generate_client_actions;
11530   output_to "src/guestfs-bindtests.c" generate_bindtests;
11531   output_to "src/guestfs-structs.pod" generate_structs_pod;
11532   output_to "src/guestfs-actions.pod" generate_actions_pod;
11533   output_to "src/guestfs-availability.pod" generate_availability_pod;
11534   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11535   output_to "src/libguestfs.syms" generate_linker_script;
11536   output_to "daemon/actions.h" generate_daemon_actions_h;
11537   output_to "daemon/stubs.c" generate_daemon_actions;
11538   output_to "daemon/names.c" generate_daemon_names;
11539   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11540   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11541   output_to "capitests/tests.c" generate_tests;
11542   output_to "fish/cmds.c" generate_fish_cmds;
11543   output_to "fish/completion.c" generate_fish_completion;
11544   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11545   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11546   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11547   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11548   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11549   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11550   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11551   output_to "perl/Guestfs.xs" generate_perl_xs;
11552   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11553   output_to "perl/bindtests.pl" generate_perl_bindtests;
11554   output_to "python/guestfs-py.c" generate_python_c;
11555   output_to "python/guestfs.py" generate_python_py;
11556   output_to "python/bindtests.py" generate_python_bindtests;
11557   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11558   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11559   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11560
11561   List.iter (
11562     fun (typ, jtyp) ->
11563       let cols = cols_of_struct typ in
11564       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11565       output_to filename (generate_java_struct jtyp cols);
11566   ) java_structs;
11567
11568   output_to "java/Makefile.inc" generate_java_makefile_inc;
11569   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11570   output_to "java/Bindtests.java" generate_java_bindtests;
11571   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11572   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11573   output_to "csharp/Libguestfs.cs" generate_csharp;
11574
11575   (* Always generate this file last, and unconditionally.  It's used
11576    * by the Makefile to know when we must re-run the generator.
11577    *)
11578   let chan = open_out "src/stamp-generator" in
11579   fprintf chan "1\n";
11580   close_out chan;
11581
11582   printf "generated %d lines of code\n" !lines