docs: Routine refresh of the documentation for guestfs(3) and guestfish(1).
[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<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.
1384
1385 The mode actually set is affected by the umask.");
1386
1387   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1388    [], (* XXX Need stat command to test *)
1389    "change file owner and group",
1390    "\
1391 Change the file owner to C<owner> and group to C<group>.
1392
1393 Only numeric uid and gid are supported.  If you want to use
1394 names, you will need to locate and parse the password file
1395 yourself (Augeas support makes this relatively easy).");
1396
1397   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1398    [InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/empty"]]);
1400     InitISOFS, Always, TestOutputTrue (
1401       [["exists"; "/directory"]])],
1402    "test if file or directory exists",
1403    "\
1404 This returns C<true> if and only if there is a file, directory
1405 (or anything) with the given C<path> name.
1406
1407 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1408
1409   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1410    [InitISOFS, Always, TestOutputTrue (
1411       [["is_file"; "/known-1"]]);
1412     InitISOFS, Always, TestOutputFalse (
1413       [["is_file"; "/directory"]])],
1414    "test if file exists",
1415    "\
1416 This returns C<true> if and only if there is a file
1417 with the given C<path> name.  Note that it returns false for
1418 other objects like directories.
1419
1420 See also C<guestfs_stat>.");
1421
1422   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1423    [InitISOFS, Always, TestOutputFalse (
1424       [["is_dir"; "/known-3"]]);
1425     InitISOFS, Always, TestOutputTrue (
1426       [["is_dir"; "/directory"]])],
1427    "test if file exists",
1428    "\
1429 This returns C<true> if and only if there is a directory
1430 with the given C<path> name.  Note that it returns false for
1431 other objects like files.
1432
1433 See also C<guestfs_stat>.");
1434
1435   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1436    [InitEmpty, Always, TestOutputListOfDevices (
1437       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1438        ["pvcreate"; "/dev/sda1"];
1439        ["pvcreate"; "/dev/sda2"];
1440        ["pvcreate"; "/dev/sda3"];
1441        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1442    "create an LVM physical volume",
1443    "\
1444 This creates an LVM physical volume on the named C<device>,
1445 where C<device> should usually be a partition name such
1446 as C</dev/sda1>.");
1447
1448   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1449    [InitEmpty, Always, TestOutputList (
1450       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1451        ["pvcreate"; "/dev/sda1"];
1452        ["pvcreate"; "/dev/sda2"];
1453        ["pvcreate"; "/dev/sda3"];
1454        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1455        ["vgcreate"; "VG2"; "/dev/sda3"];
1456        ["vgs"]], ["VG1"; "VG2"])],
1457    "create an LVM volume group",
1458    "\
1459 This creates an LVM volume group called C<volgroup>
1460 from the non-empty list of physical volumes C<physvols>.");
1461
1462   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1463    [InitEmpty, Always, TestOutputList (
1464       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1465        ["pvcreate"; "/dev/sda1"];
1466        ["pvcreate"; "/dev/sda2"];
1467        ["pvcreate"; "/dev/sda3"];
1468        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1469        ["vgcreate"; "VG2"; "/dev/sda3"];
1470        ["lvcreate"; "LV1"; "VG1"; "50"];
1471        ["lvcreate"; "LV2"; "VG1"; "50"];
1472        ["lvcreate"; "LV3"; "VG2"; "50"];
1473        ["lvcreate"; "LV4"; "VG2"; "50"];
1474        ["lvcreate"; "LV5"; "VG2"; "50"];
1475        ["lvs"]],
1476       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1477        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1478    "create an LVM logical volume",
1479    "\
1480 This creates an LVM logical volume called C<logvol>
1481 on the volume group C<volgroup>, with C<size> megabytes.");
1482
1483   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1484    [InitEmpty, Always, TestOutput (
1485       [["part_disk"; "/dev/sda"; "mbr"];
1486        ["mkfs"; "ext2"; "/dev/sda1"];
1487        ["mount_options"; ""; "/dev/sda1"; "/"];
1488        ["write_file"; "/new"; "new file contents"; "0"];
1489        ["cat"; "/new"]], "new file contents")],
1490    "make a filesystem",
1491    "\
1492 This creates a filesystem on C<device> (usually a partition
1493 or LVM logical volume).  The filesystem type is C<fstype>, for
1494 example C<ext3>.");
1495
1496   ("sfdisk", (RErr, [Device "device";
1497                      Int "cyls"; Int "heads"; Int "sectors";
1498                      StringList "lines"]), 43, [DangerWillRobinson],
1499    [],
1500    "create partitions on a block device",
1501    "\
1502 This is a direct interface to the L<sfdisk(8)> program for creating
1503 partitions on block devices.
1504
1505 C<device> should be a block device, for example C</dev/sda>.
1506
1507 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1508 and sectors on the device, which are passed directly to sfdisk as
1509 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1510 of these, then the corresponding parameter is omitted.  Usually for
1511 'large' disks, you can just pass C<0> for these, but for small
1512 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1513 out the right geometry and you will need to tell it.
1514
1515 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1516 information refer to the L<sfdisk(8)> manpage.
1517
1518 To create a single partition occupying the whole disk, you would
1519 pass C<lines> as a single element list, when the single element being
1520 the string C<,> (comma).
1521
1522 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1523 C<guestfs_part_init>");
1524
1525   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1526    [InitBasicFS, Always, TestOutput (
1527       [["write_file"; "/new"; "new file contents"; "0"];
1528        ["cat"; "/new"]], "new file contents");
1529     InitBasicFS, Always, TestOutput (
1530       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1531        ["cat"; "/new"]], "\nnew file contents\n");
1532     InitBasicFS, Always, TestOutput (
1533       [["write_file"; "/new"; "\n\n"; "0"];
1534        ["cat"; "/new"]], "\n\n");
1535     InitBasicFS, Always, TestOutput (
1536       [["write_file"; "/new"; ""; "0"];
1537        ["cat"; "/new"]], "");
1538     InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; "\n\n\n"; "0"];
1540        ["cat"; "/new"]], "\n\n\n");
1541     InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "\n"; "0"];
1543        ["cat"; "/new"]], "\n")],
1544    "create a file",
1545    "\
1546 This call creates a file called C<path>.  The contents of the
1547 file is the string C<content> (which can contain any 8 bit data),
1548 with length C<size>.
1549
1550 As a special case, if C<size> is C<0>
1551 then the length is calculated using C<strlen> (so in this case
1552 the content cannot contain embedded ASCII NULs).
1553
1554 I<NB.> Owing to a bug, writing content containing ASCII NUL
1555 characters does I<not> work, even if the length is specified.
1556 We hope to resolve this bug in a future version.  In the meantime
1557 use C<guestfs_upload>.");
1558
1559   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1560    [InitEmpty, Always, TestOutputListOfDevices (
1561       [["part_disk"; "/dev/sda"; "mbr"];
1562        ["mkfs"; "ext2"; "/dev/sda1"];
1563        ["mount_options"; ""; "/dev/sda1"; "/"];
1564        ["mounts"]], ["/dev/sda1"]);
1565     InitEmpty, Always, TestOutputList (
1566       [["part_disk"; "/dev/sda"; "mbr"];
1567        ["mkfs"; "ext2"; "/dev/sda1"];
1568        ["mount_options"; ""; "/dev/sda1"; "/"];
1569        ["umount"; "/"];
1570        ["mounts"]], [])],
1571    "unmount a filesystem",
1572    "\
1573 This unmounts the given filesystem.  The filesystem may be
1574 specified either by its mountpoint (path) or the device which
1575 contains the filesystem.");
1576
1577   ("mounts", (RStringList "devices", []), 46, [],
1578    [InitBasicFS, Always, TestOutputListOfDevices (
1579       [["mounts"]], ["/dev/sda1"])],
1580    "show mounted filesystems",
1581    "\
1582 This returns the list of currently mounted filesystems.  It returns
1583 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1584
1585 Some internal mounts are not shown.
1586
1587 See also: C<guestfs_mountpoints>");
1588
1589   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1590    [InitBasicFS, Always, TestOutputList (
1591       [["umount_all"];
1592        ["mounts"]], []);
1593     (* check that umount_all can unmount nested mounts correctly: *)
1594     InitEmpty, Always, TestOutputList (
1595       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1596        ["mkfs"; "ext2"; "/dev/sda1"];
1597        ["mkfs"; "ext2"; "/dev/sda2"];
1598        ["mkfs"; "ext2"; "/dev/sda3"];
1599        ["mount_options"; ""; "/dev/sda1"; "/"];
1600        ["mkdir"; "/mp1"];
1601        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1602        ["mkdir"; "/mp1/mp2"];
1603        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1604        ["mkdir"; "/mp1/mp2/mp3"];
1605        ["umount_all"];
1606        ["mounts"]], [])],
1607    "unmount all filesystems",
1608    "\
1609 This unmounts all mounted filesystems.
1610
1611 Some internal mounts are not unmounted by this call.");
1612
1613   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1614    [],
1615    "remove all LVM LVs, VGs and PVs",
1616    "\
1617 This command removes all LVM logical volumes, volume groups
1618 and physical volumes.");
1619
1620   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1621    [InitISOFS, Always, TestOutput (
1622       [["file"; "/empty"]], "empty");
1623     InitISOFS, Always, TestOutput (
1624       [["file"; "/known-1"]], "ASCII text");
1625     InitISOFS, Always, TestLastFail (
1626       [["file"; "/notexists"]])],
1627    "determine file type",
1628    "\
1629 This call uses the standard L<file(1)> command to determine
1630 the type or contents of the file.  This also works on devices,
1631 for example to find out whether a partition contains a filesystem.
1632
1633 This call will also transparently look inside various types
1634 of compressed file.
1635
1636 The exact command which runs is C<file -zbsL path>.  Note in
1637 particular that the filename is not prepended to the output
1638 (the C<-b> option).");
1639
1640   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1641    [InitBasicFS, Always, TestOutput (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command"; "/test-command 1"]], "Result1");
1645     InitBasicFS, Always, TestOutput (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command"; "/test-command 2"]], "Result2\n");
1649     InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 3"]], "\nResult3");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 4"]], "\nResult4\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 5"]], "\nResult5\n\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 7"]], "");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 8"]], "\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 9"]], "\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1685     InitBasicFS, Always, TestLastFail (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command"]])],
1689    "run a command from the guest filesystem",
1690    "\
1691 This call runs a command from the guest filesystem.  The
1692 filesystem must be mounted, and must contain a compatible
1693 operating system (ie. something Linux, with the same
1694 or compatible processor architecture).
1695
1696 The single parameter is an argv-style list of arguments.
1697 The first element is the name of the program to run.
1698 Subsequent elements are parameters.  The list must be
1699 non-empty (ie. must contain a program name).  Note that
1700 the command runs directly, and is I<not> invoked via
1701 the shell (see C<guestfs_sh>).
1702
1703 The return value is anything printed to I<stdout> by
1704 the command.
1705
1706 If the command returns a non-zero exit status, then
1707 this function returns an error message.  The error message
1708 string is the content of I<stderr> from the command.
1709
1710 The C<$PATH> environment variable will contain at least
1711 C</usr/bin> and C</bin>.  If you require a program from
1712 another location, you should provide the full path in the
1713 first parameter.
1714
1715 Shared libraries and data files required by the program
1716 must be available on filesystems which are mounted in the
1717 correct places.  It is the caller's responsibility to ensure
1718 all filesystems that are needed are mounted at the right
1719 locations.");
1720
1721   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1722    [InitBasicFS, Always, TestOutputList (
1723       [["upload"; "test-command"; "/test-command"];
1724        ["chmod"; "0o755"; "/test-command"];
1725        ["command_lines"; "/test-command 1"]], ["Result1"]);
1726     InitBasicFS, Always, TestOutputList (
1727       [["upload"; "test-command"; "/test-command"];
1728        ["chmod"; "0o755"; "/test-command"];
1729        ["command_lines"; "/test-command 2"]], ["Result2"]);
1730     InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 7"]], []);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 8"]], [""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 9"]], ["";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1766    "run a command, returning lines",
1767    "\
1768 This is the same as C<guestfs_command>, but splits the
1769 result into a list of lines.
1770
1771 See also: C<guestfs_sh_lines>");
1772
1773   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1774    [InitISOFS, Always, TestOutputStruct (
1775       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1776    "get file information",
1777    "\
1778 Returns file information for the given C<path>.
1779
1780 This is the same as the C<stat(2)> system call.");
1781
1782   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1783    [InitISOFS, Always, TestOutputStruct (
1784       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1785    "get file information for a symbolic link",
1786    "\
1787 Returns file information for the given C<path>.
1788
1789 This is the same as C<guestfs_stat> except that if C<path>
1790 is a symbolic link, then the link is stat-ed, not the file it
1791 refers to.
1792
1793 This is the same as the C<lstat(2)> system call.");
1794
1795   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1796    [InitISOFS, Always, TestOutputStruct (
1797       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1798    "get file system statistics",
1799    "\
1800 Returns file system statistics for any mounted file system.
1801 C<path> should be a file or directory in the mounted file system
1802 (typically it is the mount point itself, but it doesn't need to be).
1803
1804 This is the same as the C<statvfs(2)> system call.");
1805
1806   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1807    [], (* XXX test *)
1808    "get ext2/ext3/ext4 superblock details",
1809    "\
1810 This returns the contents of the ext2, ext3 or ext4 filesystem
1811 superblock on C<device>.
1812
1813 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1814 manpage for more details.  The list of fields returned isn't
1815 clearly defined, and depends on both the version of C<tune2fs>
1816 that libguestfs was built against, and the filesystem itself.");
1817
1818   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1819    [InitEmpty, Always, TestOutputTrue (
1820       [["blockdev_setro"; "/dev/sda"];
1821        ["blockdev_getro"; "/dev/sda"]])],
1822    "set block device to read-only",
1823    "\
1824 Sets the block device named C<device> to read-only.
1825
1826 This uses the L<blockdev(8)> command.");
1827
1828   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1829    [InitEmpty, Always, TestOutputFalse (
1830       [["blockdev_setrw"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-write",
1833    "\
1834 Sets the block device named C<device> to read-write.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1839    [InitEmpty, Always, TestOutputTrue (
1840       [["blockdev_setro"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "is block device set to read-only",
1843    "\
1844 Returns a boolean indicating if the block device is read-only
1845 (true if read-only, false if not).
1846
1847 This uses the L<blockdev(8)> command.");
1848
1849   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1850    [InitEmpty, Always, TestOutputInt (
1851       [["blockdev_getss"; "/dev/sda"]], 512)],
1852    "get sectorsize of block device",
1853    "\
1854 This returns the size of sectors on a block device.
1855 Usually 512, but can be larger for modern devices.
1856
1857 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1858 for that).
1859
1860 This uses the L<blockdev(8)> command.");
1861
1862   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1863    [InitEmpty, Always, TestOutputInt (
1864       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1865    "get blocksize of block device",
1866    "\
1867 This returns the block size of a device.
1868
1869 (Note this is different from both I<size in blocks> and
1870 I<filesystem block size>).
1871
1872 This uses the L<blockdev(8)> command.");
1873
1874   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1875    [], (* XXX test *)
1876    "set blocksize of block device",
1877    "\
1878 This sets the block size of a device.
1879
1880 (Note this is different from both I<size in blocks> and
1881 I<filesystem block size>).
1882
1883 This uses the L<blockdev(8)> command.");
1884
1885   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1886    [InitEmpty, Always, TestOutputInt (
1887       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1888    "get total size of device in 512-byte sectors",
1889    "\
1890 This returns the size of the device in units of 512-byte sectors
1891 (even if the sectorsize isn't 512 bytes ... weird).
1892
1893 See also C<guestfs_blockdev_getss> for the real sector size of
1894 the device, and C<guestfs_blockdev_getsize64> for the more
1895 useful I<size in bytes>.
1896
1897 This uses the L<blockdev(8)> command.");
1898
1899   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1900    [InitEmpty, Always, TestOutputInt (
1901       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1902    "get total size of device in bytes",
1903    "\
1904 This returns the size of the device in bytes.
1905
1906 See also C<guestfs_blockdev_getsz>.
1907
1908 This uses the L<blockdev(8)> command.");
1909
1910   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1911    [InitEmpty, Always, TestRun
1912       [["blockdev_flushbufs"; "/dev/sda"]]],
1913    "flush device buffers",
1914    "\
1915 This tells the kernel to flush internal buffers associated
1916 with C<device>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_rereadpt"; "/dev/sda"]]],
1923    "reread partition table",
1924    "\
1925 Reread the partition table on C<device>.
1926
1927 This uses the L<blockdev(8)> command.");
1928
1929   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1930    [InitBasicFS, Always, TestOutput (
1931       (* Pick a file from cwd which isn't likely to change. *)
1932       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1933        ["checksum"; "md5"; "/COPYING.LIB"]],
1934       Digest.to_hex (Digest.file "COPYING.LIB"))],
1935    "upload a file from the local machine",
1936    "\
1937 Upload local file C<filename> to C<remotefilename> on the
1938 filesystem.
1939
1940 C<filename> can also be a named pipe.
1941
1942 See also C<guestfs_download>.");
1943
1944   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1945    [InitBasicFS, Always, TestOutput (
1946       (* Pick a file from cwd which isn't likely to change. *)
1947       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1948        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1949        ["upload"; "testdownload.tmp"; "/upload"];
1950        ["checksum"; "md5"; "/upload"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "download a file to the local machine",
1953    "\
1954 Download file C<remotefilename> and save it as C<filename>
1955 on the local machine.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_upload>, C<guestfs_cat>.");
1960
1961   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1962    [InitISOFS, Always, TestOutput (
1963       [["checksum"; "crc"; "/known-3"]], "2891671662");
1964     InitISOFS, Always, TestLastFail (
1965       [["checksum"; "crc"; "/notexists"]]);
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.");
2020
2021   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2022    [InitBasicFS, Always, TestOutput (
2023       [["tar_in"; "../images/helloworld.tar"; "/"];
2024        ["cat"; "/hello"]], "hello\n")],
2025    "unpack tarfile to directory",
2026    "\
2027 This command uploads and unpacks local file C<tarfile> (an
2028 I<uncompressed> tar file) into C<directory>.
2029
2030 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2031
2032   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2033    [],
2034    "pack directory into tarfile",
2035    "\
2036 This command packs the contents of C<directory> and downloads
2037 it to local file C<tarfile>.
2038
2039 To download a compressed tarball, use C<guestfs_tgz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
2705    [InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
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/*/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/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.
2979
2980 Note that, just like L<mknod(2)>, the mode must be bitwise
2981 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
2982 just creates a regular file).  These constants are
2983 available in the standard Linux header files, or you can use
2984 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
2985 which are wrappers around this command which bitwise OR
2986 in the appropriate constant for you.
2987
2988 The mode actually set is affected by the umask.");
2989
2990   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mkfifo"; "0o777"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2994    "make FIFO (named pipe)",
2995    "\
2996 This call creates a FIFO (named pipe) called C<path> with
2997 mode C<mode>.  It is just a convenient wrapper around
2998 C<guestfs_mknod>.
2999
3000 The mode actually set is affected by the umask.");
3001
3002   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3003    [InitBasicFS, Always, TestOutputStruct (
3004       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3005        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3006    "make block device node",
3007    "\
3008 This call creates a block device node called C<path> with
3009 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3010 It is just a convenient wrapper around C<guestfs_mknod>.
3011
3012 The mode actually set is affected by the umask.");
3013
3014   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3015    [InitBasicFS, Always, TestOutputStruct (
3016       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3017        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3018    "make char device node",
3019    "\
3020 This call creates a char device node called C<path> with
3021 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3022 It is just a convenient wrapper around C<guestfs_mknod>.
3023
3024 The mode actually set is affected by the umask.");
3025
3026   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3027    [InitEmpty, Always, TestOutputInt (
3028       [["umask"; "0o22"]], 0o22)],
3029    "set file mode creation mask (umask)",
3030    "\
3031 This function sets the mask used for creating new files and
3032 device nodes to C<mask & 0777>.
3033
3034 Typical umask values would be C<022> which creates new files
3035 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3036 C<002> which creates new files with permissions like
3037 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3038
3039 The default umask is C<022>.  This is important because it
3040 means that directories and device nodes will be created with
3041 C<0644> or C<0755> mode even if you specify C<0777>.
3042
3043 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3044
3045 This call returns the previous umask.");
3046
3047   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3048    [],
3049    "read directories entries",
3050    "\
3051 This returns the list of directory entries in directory C<dir>.
3052
3053 All entries in the directory are returned, including C<.> and
3054 C<..>.  The entries are I<not> sorted, but returned in the same
3055 order as the underlying filesystem.
3056
3057 Also this call returns basic file type information about each
3058 file.  The C<ftyp> field will contain one of the following characters:
3059
3060 =over 4
3061
3062 =item 'b'
3063
3064 Block special
3065
3066 =item 'c'
3067
3068 Char special
3069
3070 =item 'd'
3071
3072 Directory
3073
3074 =item 'f'
3075
3076 FIFO (named pipe)
3077
3078 =item 'l'
3079
3080 Symbolic link
3081
3082 =item 'r'
3083
3084 Regular file
3085
3086 =item 's'
3087
3088 Socket
3089
3090 =item 'u'
3091
3092 Unknown file type
3093
3094 =item '?'
3095
3096 The L<readdir(3)> returned a C<d_type> field with an
3097 unexpected value
3098
3099 =back
3100
3101 This function is primarily intended for use by programs.  To
3102 get a simple list of names, use C<guestfs_ls>.  To get a printable
3103 directory for human consumption, use C<guestfs_ll>.");
3104
3105   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3106    [],
3107    "create partitions on a block device",
3108    "\
3109 This is a simplified interface to the C<guestfs_sfdisk>
3110 command, where partition sizes are specified in megabytes
3111 only (rounded to the nearest cylinder) and you don't need
3112 to specify the cyls, heads and sectors parameters which
3113 were rarely if ever used anyway.
3114
3115 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3116 and C<guestfs_part_disk>");
3117
3118   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3119    [],
3120    "determine file type inside a compressed file",
3121    "\
3122 This command runs C<file> after first decompressing C<path>
3123 using C<method>.
3124
3125 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3126
3127 Since 1.0.63, use C<guestfs_file> instead which can now
3128 process compressed files.");
3129
3130   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3131    [],
3132    "list extended attributes of a file or directory",
3133    "\
3134 This call lists the extended attributes of the file or directory
3135 C<path>.
3136
3137 At the system call level, this is a combination of the
3138 L<listxattr(2)> and L<getxattr(2)> calls.
3139
3140 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3141
3142   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3143    [],
3144    "list extended attributes of a file or directory",
3145    "\
3146 This is the same as C<guestfs_getxattrs>, but if C<path>
3147 is a symbolic link, then it returns the extended attributes
3148 of the link itself.");
3149
3150   ("setxattr", (RErr, [String "xattr";
3151                        String "val"; Int "vallen"; (* will be BufferIn *)
3152                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3153    [],
3154    "set extended attribute of a file or directory",
3155    "\
3156 This call sets the extended attribute named C<xattr>
3157 of the file C<path> to the value C<val> (of length C<vallen>).
3158 The value is arbitrary 8 bit data.
3159
3160 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3161
3162   ("lsetxattr", (RErr, [String "xattr";
3163                         String "val"; Int "vallen"; (* will be BufferIn *)
3164                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3165    [],
3166    "set extended attribute of a file or directory",
3167    "\
3168 This is the same as C<guestfs_setxattr>, but if C<path>
3169 is a symbolic link, then it sets an extended attribute
3170 of the link itself.");
3171
3172   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3173    [],
3174    "remove extended attribute of a file or directory",
3175    "\
3176 This call removes the extended attribute named C<xattr>
3177 of the file C<path>.
3178
3179 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3180
3181   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3182    [],
3183    "remove extended attribute of a file or directory",
3184    "\
3185 This is the same as C<guestfs_removexattr>, but if C<path>
3186 is a symbolic link, then it removes an extended attribute
3187 of the link itself.");
3188
3189   ("mountpoints", (RHashtable "mps", []), 147, [],
3190    [],
3191    "show mountpoints",
3192    "\
3193 This call is similar to C<guestfs_mounts>.  That call returns
3194 a list of devices.  This one returns a hash table (map) of
3195 device name to directory where the device is mounted.");
3196
3197   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3198    (* This is a special case: while you would expect a parameter
3199     * of type "Pathname", that doesn't work, because it implies
3200     * NEED_ROOT in the generated calling code in stubs.c, and
3201     * this function cannot use NEED_ROOT.
3202     *)
3203    [],
3204    "create a mountpoint",
3205    "\
3206 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3207 specialized calls that can be used to create extra mountpoints
3208 before mounting the first filesystem.
3209
3210 These calls are I<only> necessary in some very limited circumstances,
3211 mainly the case where you want to mount a mix of unrelated and/or
3212 read-only filesystems together.
3213
3214 For example, live CDs often contain a \"Russian doll\" nest of
3215 filesystems, an ISO outer layer, with a squashfs image inside, with
3216 an ext2/3 image inside that.  You can unpack this as follows
3217 in guestfish:
3218
3219  add-ro Fedora-11-i686-Live.iso
3220  run
3221  mkmountpoint /cd
3222  mkmountpoint /squash
3223  mkmountpoint /ext3
3224  mount /dev/sda /cd
3225  mount-loop /cd/LiveOS/squashfs.img /squash
3226  mount-loop /squash/LiveOS/ext3fs.img /ext3
3227
3228 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3229
3230   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3231    [],
3232    "remove a mountpoint",
3233    "\
3234 This calls removes a mountpoint that was previously created
3235 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3236 for full details.");
3237
3238   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3239    [InitISOFS, Always, TestOutputBuffer (
3240       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3241    "read a file",
3242    "\
3243 This calls returns the contents of the file C<path> as a
3244 buffer.
3245
3246 Unlike C<guestfs_cat>, this function can correctly
3247 handle files that contain embedded ASCII NUL characters.
3248 However unlike C<guestfs_download>, this function is limited
3249 in the total size of file that can be handled.");
3250
3251   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3252    [InitISOFS, Always, TestOutputList (
3253       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3254     InitISOFS, Always, TestOutputList (
3255       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3256    "return lines matching a pattern",
3257    "\
3258 This calls the external C<grep> program and returns the
3259 matching lines.");
3260
3261   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3262    [InitISOFS, Always, TestOutputList (
3263       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3264    "return lines matching a pattern",
3265    "\
3266 This calls the external C<egrep> program and returns the
3267 matching lines.");
3268
3269   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3270    [InitISOFS, Always, TestOutputList (
3271       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3272    "return lines matching a pattern",
3273    "\
3274 This calls the external C<fgrep> program and returns the
3275 matching lines.");
3276
3277   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3278    [InitISOFS, Always, TestOutputList (
3279       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3280    "return lines matching a pattern",
3281    "\
3282 This calls the external C<grep -i> program and returns the
3283 matching lines.");
3284
3285   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3286    [InitISOFS, Always, TestOutputList (
3287       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3288    "return lines matching a pattern",
3289    "\
3290 This calls the external C<egrep -i> program and returns the
3291 matching lines.");
3292
3293   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3294    [InitISOFS, Always, TestOutputList (
3295       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3296    "return lines matching a pattern",
3297    "\
3298 This calls the external C<fgrep -i> program and returns the
3299 matching lines.");
3300
3301   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputList (
3303       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3304    "return lines matching a pattern",
3305    "\
3306 This calls the external C<zgrep> program and returns the
3307 matching lines.");
3308
3309   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3310    [InitISOFS, Always, TestOutputList (
3311       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3312    "return lines matching a pattern",
3313    "\
3314 This calls the external C<zegrep> program and returns the
3315 matching lines.");
3316
3317   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3318    [InitISOFS, Always, TestOutputList (
3319       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3320    "return lines matching a pattern",
3321    "\
3322 This calls the external C<zfgrep> program and returns the
3323 matching lines.");
3324
3325   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3326    [InitISOFS, Always, TestOutputList (
3327       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3328    "return lines matching a pattern",
3329    "\
3330 This calls the external C<zgrep -i> program and returns the
3331 matching lines.");
3332
3333   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3334    [InitISOFS, Always, TestOutputList (
3335       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3336    "return lines matching a pattern",
3337    "\
3338 This calls the external C<zegrep -i> program and returns the
3339 matching lines.");
3340
3341   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3342    [InitISOFS, Always, TestOutputList (
3343       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3344    "return lines matching a pattern",
3345    "\
3346 This calls the external C<zfgrep -i> program and returns the
3347 matching lines.");
3348
3349   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3350    [InitISOFS, Always, TestOutput (
3351       [["realpath"; "/../directory"]], "/directory")],
3352    "canonicalized absolute pathname",
3353    "\
3354 Return the canonicalized absolute pathname of C<path>.  The
3355 returned path has no C<.>, C<..> or symbolic link path elements.");
3356
3357   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3358    [InitBasicFS, Always, TestOutputStruct (
3359       [["touch"; "/a"];
3360        ["ln"; "/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> command.");
3365
3366   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3367    [InitBasicFS, Always, TestOutputStruct (
3368       [["touch"; "/a"];
3369        ["touch"; "/b"];
3370        ["ln_f"; "/a"; "/b"];
3371        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3372    "create a hard link",
3373    "\
3374 This command creates a hard link using the C<ln -f> command.
3375 The C<-f> option removes the link (C<linkname>) if it exists already.");
3376
3377   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3378    [InitBasicFS, Always, TestOutputStruct (
3379       [["touch"; "/a"];
3380        ["ln_s"; "a"; "/b"];
3381        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3382    "create a symbolic link",
3383    "\
3384 This command creates a symbolic link using the C<ln -s> command.");
3385
3386   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3387    [InitBasicFS, Always, TestOutput (
3388       [["mkdir_p"; "/a/b"];
3389        ["touch"; "/a/b/c"];
3390        ["ln_sf"; "../d"; "/a/b/c"];
3391        ["readlink"; "/a/b/c"]], "../d")],
3392    "create a symbolic link",
3393    "\
3394 This command creates a symbolic link using the C<ln -sf> command,
3395 The C<-f> option removes the link (C<linkname>) if it exists already.");
3396
3397   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3398    [] (* XXX tested above *),
3399    "read the target of a symbolic link",
3400    "\
3401 This command reads the target of a symbolic link.");
3402
3403   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3404    [InitBasicFS, Always, TestOutputStruct (
3405       [["fallocate"; "/a"; "1000000"];
3406        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3407    "preallocate a file in the guest filesystem",
3408    "\
3409 This command preallocates a file (containing zero bytes) named
3410 C<path> of size C<len> bytes.  If the file exists already, it
3411 is overwritten.
3412
3413 Do not confuse this with the guestfish-specific
3414 C<alloc> command which allocates a file in the host and
3415 attaches it as a device.");
3416
3417   ("swapon_device", (RErr, [Device "device"]), 170, [],
3418    [InitPartition, Always, TestRun (
3419       [["mkswap"; "/dev/sda1"];
3420        ["swapon_device"; "/dev/sda1"];
3421        ["swapoff_device"; "/dev/sda1"]])],
3422    "enable swap on device",
3423    "\
3424 This command enables the libguestfs appliance to use the
3425 swap device or partition named C<device>.  The increased
3426 memory is made available for all commands, for example
3427 those run using C<guestfs_command> or C<guestfs_sh>.
3428
3429 Note that you should not swap to existing guest swap
3430 partitions unless you know what you are doing.  They may
3431 contain hibernation information, or other information that
3432 the guest doesn't want you to trash.  You also risk leaking
3433 information about the host to the guest this way.  Instead,
3434 attach a new host device to the guest and swap on that.");
3435
3436   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3437    [], (* XXX tested by swapon_device *)
3438    "disable swap on device",
3439    "\
3440 This command disables the libguestfs appliance swap
3441 device or partition named C<device>.
3442 See C<guestfs_swapon_device>.");
3443
3444   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3445    [InitBasicFS, Always, TestRun (
3446       [["fallocate"; "/swap"; "8388608"];
3447        ["mkswap_file"; "/swap"];
3448        ["swapon_file"; "/swap"];
3449        ["swapoff_file"; "/swap"]])],
3450    "enable swap on file",
3451    "\
3452 This command enables swap to a file.
3453 See C<guestfs_swapon_device> for other notes.");
3454
3455   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3456    [], (* XXX tested by swapon_file *)
3457    "disable swap on file",
3458    "\
3459 This command disables the libguestfs appliance swap on file.");
3460
3461   ("swapon_label", (RErr, [String "label"]), 174, [],
3462    [InitEmpty, Always, TestRun (
3463       [["part_disk"; "/dev/sdb"; "mbr"];
3464        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3465        ["swapon_label"; "swapit"];
3466        ["swapoff_label"; "swapit"];
3467        ["zero"; "/dev/sdb"];
3468        ["blockdev_rereadpt"; "/dev/sdb"]])],
3469    "enable swap on labeled swap partition",
3470    "\
3471 This command enables swap to a labeled swap partition.
3472 See C<guestfs_swapon_device> for other notes.");
3473
3474   ("swapoff_label", (RErr, [String "label"]), 175, [],
3475    [], (* XXX tested by swapon_label *)
3476    "disable swap on labeled swap partition",
3477    "\
3478 This command disables the libguestfs appliance swap on
3479 labeled swap partition.");
3480
3481   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3482    (let uuid = uuidgen () in
3483     [InitEmpty, Always, TestRun (
3484        [["mkswap_U"; uuid; "/dev/sdb"];
3485         ["swapon_uuid"; uuid];
3486         ["swapoff_uuid"; uuid]])]),
3487    "enable swap on swap partition by UUID",
3488    "\
3489 This command enables swap to a swap partition with the given UUID.
3490 See C<guestfs_swapon_device> for other notes.");
3491
3492   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3493    [], (* XXX tested by swapon_uuid *)
3494    "disable swap on swap partition by UUID",
3495    "\
3496 This command disables the libguestfs appliance swap partition
3497 with the given UUID.");
3498
3499   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3500    [InitBasicFS, Always, TestRun (
3501       [["fallocate"; "/swap"; "8388608"];
3502        ["mkswap_file"; "/swap"]])],
3503    "create a swap file",
3504    "\
3505 Create a swap file.
3506
3507 This command just writes a swap file signature to an existing
3508 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3509
3510   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3511    [InitISOFS, Always, TestRun (
3512       [["inotify_init"; "0"]])],
3513    "create an inotify handle",
3514    "\
3515 This command creates a new inotify handle.
3516 The inotify subsystem can be used to notify events which happen to
3517 objects in the guest filesystem.
3518
3519 C<maxevents> is the maximum number of events which will be
3520 queued up between calls to C<guestfs_inotify_read> or
3521 C<guestfs_inotify_files>.
3522 If this is passed as C<0>, then the kernel (or previously set)
3523 default is used.  For Linux 2.6.29 the default was 16384 events.
3524 Beyond this limit, the kernel throws away events, but records
3525 the fact that it threw them away by setting a flag
3526 C<IN_Q_OVERFLOW> in the returned structure list (see
3527 C<guestfs_inotify_read>).
3528
3529 Before any events are generated, you have to add some
3530 watches to the internal watch list.  See:
3531 C<guestfs_inotify_add_watch>,
3532 C<guestfs_inotify_rm_watch> and
3533 C<guestfs_inotify_watch_all>.
3534
3535 Queued up events should be read periodically by calling
3536 C<guestfs_inotify_read>
3537 (or C<guestfs_inotify_files> which is just a helpful
3538 wrapper around C<guestfs_inotify_read>).  If you don't
3539 read the events out often enough then you risk the internal
3540 queue overflowing.
3541
3542 The handle should be closed after use by calling
3543 C<guestfs_inotify_close>.  This also removes any
3544 watches automatically.
3545
3546 See also L<inotify(7)> for an overview of the inotify interface
3547 as exposed by the Linux kernel, which is roughly what we expose
3548 via libguestfs.  Note that there is one global inotify handle
3549 per libguestfs instance.");
3550
3551   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3552    [InitBasicFS, Always, TestOutputList (
3553       [["inotify_init"; "0"];
3554        ["inotify_add_watch"; "/"; "1073741823"];
3555        ["touch"; "/a"];
3556        ["touch"; "/b"];
3557        ["inotify_files"]], ["a"; "b"])],
3558    "add an inotify watch",
3559    "\
3560 Watch C<path> for the events listed in C<mask>.
3561
3562 Note that if C<path> is a directory then events within that
3563 directory are watched, but this does I<not> happen recursively
3564 (in subdirectories).
3565
3566 Note for non-C or non-Linux callers: the inotify events are
3567 defined by the Linux kernel ABI and are listed in
3568 C</usr/include/sys/inotify.h>.");
3569
3570   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3571    [],
3572    "remove an inotify watch",
3573    "\
3574 Remove a previously defined inotify watch.
3575 See C<guestfs_inotify_add_watch>.");
3576
3577   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3578    [],
3579    "return list of inotify events",
3580    "\
3581 Return the complete queue of events that have happened
3582 since the previous read call.
3583
3584 If no events have happened, this returns an empty list.
3585
3586 I<Note>: In order to make sure that all events have been
3587 read, you must call this function repeatedly until it
3588 returns an empty list.  The reason is that the call will
3589 read events up to the maximum appliance-to-host message
3590 size and leave remaining events in the queue.");
3591
3592   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3593    [],
3594    "return list of watched files that had events",
3595    "\
3596 This function is a helpful wrapper around C<guestfs_inotify_read>
3597 which just returns a list of pathnames of objects that were
3598 touched.  The returned pathnames are sorted and deduplicated.");
3599
3600   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3601    [],
3602    "close the inotify handle",
3603    "\
3604 This closes the inotify handle which was previously
3605 opened by inotify_init.  It removes all watches, throws
3606 away any pending events, and deallocates all resources.");
3607
3608   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3609    [],
3610    "set SELinux security context",
3611    "\
3612 This sets the SELinux security context of the daemon
3613 to the string C<context>.
3614
3615 See the documentation about SELINUX in L<guestfs(3)>.");
3616
3617   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3618    [],
3619    "get SELinux security context",
3620    "\
3621 This gets the SELinux security context of the daemon.
3622
3623 See the documentation about SELINUX in L<guestfs(3)>,
3624 and C<guestfs_setcon>");
3625
3626   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3627    [InitEmpty, Always, TestOutput (
3628       [["part_disk"; "/dev/sda"; "mbr"];
3629        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda1"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make a filesystem with block size",
3634    "\
3635 This call is similar to C<guestfs_mkfs>, but it allows you to
3636 control the block size of the resulting filesystem.  Supported
3637 block sizes depend on the filesystem type, but typically they
3638 are C<1024>, C<2048> or C<4096> only.");
3639
3640   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal"; "4096"; "/dev/sda1"];
3644        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3645        ["mount_options"; ""; "/dev/sda2"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make ext2/3/4 external journal",
3649    "\
3650 This creates an ext2 external journal on C<device>.  It is equivalent
3651 to the command:
3652
3653  mke2fs -O journal_dev -b blocksize device");
3654
3655   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3656    [InitEmpty, Always, TestOutput (
3657       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3658        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3659        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3660        ["mount_options"; ""; "/dev/sda2"; "/"];
3661        ["write_file"; "/new"; "new file contents"; "0"];
3662        ["cat"; "/new"]], "new file contents")],
3663    "make ext2/3/4 external journal with label",
3664    "\
3665 This creates an ext2 external journal on C<device> with label C<label>.");
3666
3667   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3668    (let uuid = uuidgen () in
3669     [InitEmpty, Always, TestOutput (
3670        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3671         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3672         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3673         ["mount_options"; ""; "/dev/sda2"; "/"];
3674         ["write_file"; "/new"; "new file contents"; "0"];
3675         ["cat"; "/new"]], "new file contents")]),
3676    "make ext2/3/4 external journal with UUID",
3677    "\
3678 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3679
3680   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3681    [],
3682    "make ext2/3/4 filesystem with external journal",
3683    "\
3684 This creates an ext2/3/4 filesystem on C<device> with
3685 an external journal on C<journal>.  It is equivalent
3686 to the command:
3687
3688  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3689
3690 See also C<guestfs_mke2journal>.");
3691
3692   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3693    [],
3694    "make ext2/3/4 filesystem with external journal",
3695    "\
3696 This creates an ext2/3/4 filesystem on C<device> with
3697 an external journal on the journal labeled C<label>.
3698
3699 See also C<guestfs_mke2journal_L>.");
3700
3701   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3702    [],
3703    "make ext2/3/4 filesystem with external journal",
3704    "\
3705 This creates an ext2/3/4 filesystem on C<device> with
3706 an external journal on the journal with UUID C<uuid>.
3707
3708 See also C<guestfs_mke2journal_U>.");
3709
3710   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3711    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3712    "load a kernel module",
3713    "\
3714 This loads a kernel module in the appliance.
3715
3716 The kernel module must have been whitelisted when libguestfs
3717 was built (see C<appliance/kmod.whitelist.in> in the source).");
3718
3719   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3720    [InitNone, Always, TestOutput (
3721       [["echo_daemon"; "This is a test"]], "This is a test"
3722     )],
3723    "echo arguments back to the client",
3724    "\
3725 This command concatenate the list of C<words> passed with single spaces between
3726 them and returns the resulting string.
3727
3728 You can use this command to test the connection through to the daemon.
3729
3730 See also C<guestfs_ping_daemon>.");
3731
3732   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3733    [], (* There is a regression test for this. *)
3734    "find all files and directories, returning NUL-separated list",
3735    "\
3736 This command lists out all files and directories, recursively,
3737 starting at C<directory>, placing the resulting list in the
3738 external file called C<files>.
3739
3740 This command works the same way as C<guestfs_find> with the
3741 following exceptions:
3742
3743 =over 4
3744
3745 =item *
3746
3747 The resulting list is written to an external file.
3748
3749 =item *
3750
3751 Items (filenames) in the result are separated
3752 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3753
3754 =item *
3755
3756 This command is not limited in the number of names that it
3757 can return.
3758
3759 =item *
3760
3761 The result list is not sorted.
3762
3763 =back");
3764
3765   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3766    [InitISOFS, Always, TestOutput (
3767       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3768     InitISOFS, Always, TestOutput (
3769       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3770     InitISOFS, Always, TestOutput (
3771       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3772     InitISOFS, Always, TestLastFail (
3773       [["case_sensitive_path"; "/Known-1/"]]);
3774     InitBasicFS, Always, TestOutput (
3775       [["mkdir"; "/a"];
3776        ["mkdir"; "/a/bbb"];
3777        ["touch"; "/a/bbb/c"];
3778        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3779     InitBasicFS, Always, TestOutput (
3780       [["mkdir"; "/a"];
3781        ["mkdir"; "/a/bbb"];
3782        ["touch"; "/a/bbb/c"];
3783        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3784     InitBasicFS, Always, TestLastFail (
3785       [["mkdir"; "/a"];
3786        ["mkdir"; "/a/bbb"];
3787        ["touch"; "/a/bbb/c"];
3788        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3789    "return true path on case-insensitive filesystem",
3790    "\
3791 This can be used to resolve case insensitive paths on
3792 a filesystem which is case sensitive.  The use case is
3793 to resolve paths which you have read from Windows configuration
3794 files or the Windows Registry, to the true path.
3795
3796 The command handles a peculiarity of the Linux ntfs-3g
3797 filesystem driver (and probably others), which is that although
3798 the underlying filesystem is case-insensitive, the driver
3799 exports the filesystem to Linux as case-sensitive.
3800
3801 One consequence of this is that special directories such
3802 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3803 (or other things) depending on the precise details of how
3804 they were created.  In Windows itself this would not be
3805 a problem.
3806
3807 Bug or feature?  You decide:
3808 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3809
3810 This function resolves the true case of each element in the
3811 path and returns the case-sensitive path.
3812
3813 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3814 might return C<\"/WINDOWS/system32\"> (the exact return value
3815 would depend on details of how the directories were originally
3816 created under Windows).
3817
3818 I<Note>:
3819 This function does not handle drive names, backslashes etc.
3820
3821 See also C<guestfs_realpath>.");
3822
3823   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3824    [InitBasicFS, Always, TestOutput (
3825       [["vfs_type"; "/dev/sda1"]], "ext2")],
3826    "get the Linux VFS type corresponding to a mounted device",
3827    "\
3828 This command gets the block device type corresponding to
3829 a mounted device called C<device>.
3830
3831 Usually the result is the name of the Linux VFS module that
3832 is used to mount this device (probably determined automatically
3833 if you used the C<guestfs_mount> call).");
3834
3835   ("truncate", (RErr, [Pathname "path"]), 199, [],
3836    [InitBasicFS, Always, TestOutputStruct (
3837       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3838        ["truncate"; "/test"];
3839        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3840    "truncate a file to zero size",
3841    "\
3842 This command truncates C<path> to a zero-length file.  The
3843 file must exist already.");
3844
3845   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3846    [InitBasicFS, Always, TestOutputStruct (
3847       [["touch"; "/test"];
3848        ["truncate_size"; "/test"; "1000"];
3849        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3850    "truncate a file to a particular size",
3851    "\
3852 This command truncates C<path> to size C<size> bytes.  The file
3853 must exist already.  If the file is smaller than C<size> then
3854 the file is extended to the required size with null bytes.");
3855
3856   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3857    [InitBasicFS, Always, TestOutputStruct (
3858       [["touch"; "/test"];
3859        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3860        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3861    "set timestamp of a file with nanosecond precision",
3862    "\
3863 This command sets the timestamps of a file with nanosecond
3864 precision.
3865
3866 C<atsecs, atnsecs> are the last access time (atime) in secs and
3867 nanoseconds from the epoch.
3868
3869 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3870 secs and nanoseconds from the epoch.
3871
3872 If the C<*nsecs> field contains the special value C<-1> then
3873 the corresponding timestamp is set to the current time.  (The
3874 C<*secs> field is ignored in this case).
3875
3876 If the C<*nsecs> field contains the special value C<-2> then
3877 the corresponding timestamp is left unchanged.  (The
3878 C<*secs> field is ignored in this case).");
3879
3880   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3881    [InitBasicFS, Always, TestOutputStruct (
3882       [["mkdir_mode"; "/test"; "0o111"];
3883        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3884    "create a directory with a particular mode",
3885    "\
3886 This command creates a directory, setting the initial permissions
3887 of the directory to C<mode>.
3888
3889 For common Linux filesystems, the actual mode which is set will
3890 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3891 interpret the mode in other ways.
3892
3893 See also C<guestfs_mkdir>, C<guestfs_umask>");
3894
3895   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3896    [], (* XXX *)
3897    "change file owner and group",
3898    "\
3899 Change the file owner to C<owner> and group to C<group>.
3900 This is like C<guestfs_chown> but if C<path> is a symlink then
3901 the link itself is changed, not the target.
3902
3903 Only numeric uid and gid are supported.  If you want to use
3904 names, you will need to locate and parse the password file
3905 yourself (Augeas support makes this relatively easy).");
3906
3907   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3908    [], (* XXX *)
3909    "lstat on multiple files",
3910    "\
3911 This call allows you to perform the C<guestfs_lstat> operation
3912 on multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3914
3915 On return you get a list of stat structs, with a one-to-one
3916 correspondence to the C<names> list.  If any name did not exist
3917 or could not be lstat'd, then the C<ino> field of that structure
3918 is set to C<-1>.
3919
3920 This call is intended for programs that want to efficiently
3921 list a directory contents without making many round-trips.
3922 See also C<guestfs_lxattrlist> for a similarly efficient call
3923 for getting extended attributes.  Very long directory listings
3924 might cause the protocol message size to be exceeded, causing
3925 this call to fail.  The caller must split up such requests
3926 into smaller groups of names.");
3927
3928   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3929    [], (* XXX *)
3930    "lgetxattr on multiple files",
3931    "\
3932 This call allows you to get the extended attributes
3933 of multiple files, where all files are in the directory C<path>.
3934 C<names> is the list of files from this directory.
3935
3936 On return you get a flat list of xattr structs which must be
3937 interpreted sequentially.  The first xattr struct always has a zero-length
3938 C<attrname>.  C<attrval> in this struct is zero-length
3939 to indicate there was an error doing C<lgetxattr> for this
3940 file, I<or> is a C string which is a decimal number
3941 (the number of following attributes for this file, which could
3942 be C<\"0\">).  Then after the first xattr struct are the
3943 zero or more attributes for the first named file.
3944 This repeats for the second and subsequent files.
3945
3946 This call is intended for programs that want to efficiently
3947 list a directory contents without making many round-trips.
3948 See also C<guestfs_lstatlist> for a similarly efficient call
3949 for getting standard stats.  Very long directory listings
3950 might cause the protocol message size to be exceeded, causing
3951 this call to fail.  The caller must split up such requests
3952 into smaller groups of names.");
3953
3954   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3955    [], (* XXX *)
3956    "readlink on multiple files",
3957    "\
3958 This call allows you to do a C<readlink> operation
3959 on multiple files, where all files are in the directory C<path>.
3960 C<names> is the list of files from this directory.
3961
3962 On return you get a list of strings, with a one-to-one
3963 correspondence to the C<names> list.  Each string is the
3964 value of the symbol link.
3965
3966 If the C<readlink(2)> operation fails on any name, then
3967 the corresponding result string is the empty string C<\"\">.
3968 However the whole operation is completed even if there
3969 were C<readlink(2)> errors, and so you can call this
3970 function with names where you don't know if they are
3971 symbolic links already (albeit slightly less efficient).
3972
3973 This call is intended for programs that want to efficiently
3974 list a directory contents without making many round-trips.
3975 Very long directory listings might cause the protocol
3976 message size to be exceeded, causing
3977 this call to fail.  The caller must split up such requests
3978 into smaller groups of names.");
3979
3980   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3981    [InitISOFS, Always, TestOutputBuffer (
3982       [["pread"; "/known-4"; "1"; "3"]], "\n");
3983     InitISOFS, Always, TestOutputBuffer (
3984       [["pread"; "/empty"; "0"; "100"]], "")],
3985    "read part of a file",
3986    "\
3987 This command lets you read part of a file.  It reads C<count>
3988 bytes of the file, starting at C<offset>, from file C<path>.
3989
3990 This may read fewer bytes than requested.  For further details
3991 see the L<pread(2)> system call.");
3992
3993   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3994    [InitEmpty, Always, TestRun (
3995       [["part_init"; "/dev/sda"; "gpt"]])],
3996    "create an empty partition table",
3997    "\
3998 This creates an empty partition table on C<device> of one of the
3999 partition types listed below.  Usually C<parttype> should be
4000 either C<msdos> or C<gpt> (for large disks).
4001
4002 Initially there are no partitions.  Following this, you should
4003 call C<guestfs_part_add> for each partition required.
4004
4005 Possible values for C<parttype> are:
4006
4007 =over 4
4008
4009 =item B<efi> | B<gpt>
4010
4011 Intel EFI / GPT partition table.
4012
4013 This is recommended for >= 2 TB partitions that will be accessed
4014 from Linux and Intel-based Mac OS X.  It also has limited backwards
4015 compatibility with the C<mbr> format.
4016
4017 =item B<mbr> | B<msdos>
4018
4019 The standard PC \"Master Boot Record\" (MBR) format used
4020 by MS-DOS and Windows.  This partition type will B<only> work
4021 for device sizes up to 2 TB.  For large disks we recommend
4022 using C<gpt>.
4023
4024 =back
4025
4026 Other partition table types that may work but are not
4027 supported include:
4028
4029 =over 4
4030
4031 =item B<aix>
4032
4033 AIX disk labels.
4034
4035 =item B<amiga> | B<rdb>
4036
4037 Amiga \"Rigid Disk Block\" format.
4038
4039 =item B<bsd>
4040
4041 BSD disk labels.
4042
4043 =item B<dasd>
4044
4045 DASD, used on IBM mainframes.
4046
4047 =item B<dvh>
4048
4049 MIPS/SGI volumes.
4050
4051 =item B<mac>
4052
4053 Old Mac partition format.  Modern Macs use C<gpt>.
4054
4055 =item B<pc98>
4056
4057 NEC PC-98 format, common in Japan apparently.
4058
4059 =item B<sun>
4060
4061 Sun disk labels.
4062
4063 =back");
4064
4065   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4066    [InitEmpty, Always, TestRun (
4067       [["part_init"; "/dev/sda"; "mbr"];
4068        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4069     InitEmpty, Always, TestRun (
4070       [["part_init"; "/dev/sda"; "gpt"];
4071        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4072        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4073     InitEmpty, Always, TestRun (
4074       [["part_init"; "/dev/sda"; "mbr"];
4075        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4076        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4077        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4078        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4079    "add a partition to the device",
4080    "\
4081 This command adds a partition to C<device>.  If there is no partition
4082 table on the device, call C<guestfs_part_init> first.
4083
4084 The C<prlogex> parameter is the type of partition.  Normally you
4085 should pass C<p> or C<primary> here, but MBR partition tables also
4086 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4087 types.
4088
4089 C<startsect> and C<endsect> are the start and end of the partition
4090 in I<sectors>.  C<endsect> may be negative, which means it counts
4091 backwards from the end of the disk (C<-1> is the last sector).
4092
4093 Creating a partition which covers the whole disk is not so easy.
4094 Use C<guestfs_part_disk> to do that.");
4095
4096   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4097    [InitEmpty, Always, TestRun (
4098       [["part_disk"; "/dev/sda"; "mbr"]]);
4099     InitEmpty, Always, TestRun (
4100       [["part_disk"; "/dev/sda"; "gpt"]])],
4101    "partition whole disk with a single primary partition",
4102    "\
4103 This command is simply a combination of C<guestfs_part_init>
4104 followed by C<guestfs_part_add> to create a single primary partition
4105 covering the whole disk.
4106
4107 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4108 but other possible values are described in C<guestfs_part_init>.");
4109
4110   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4111    [InitEmpty, Always, TestRun (
4112       [["part_disk"; "/dev/sda"; "mbr"];
4113        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4114    "make a partition bootable",
4115    "\
4116 This sets the bootable flag on partition numbered C<partnum> on
4117 device C<device>.  Note that partitions are numbered from 1.
4118
4119 The bootable flag is used by some operating systems (notably
4120 Windows) to determine which partition to boot from.  It is by
4121 no means universally recognized.");
4122
4123   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4124    [InitEmpty, Always, TestRun (
4125       [["part_disk"; "/dev/sda"; "gpt"];
4126        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4127    "set partition name",
4128    "\
4129 This sets the partition name on partition numbered C<partnum> on
4130 device C<device>.  Note that partitions are numbered from 1.
4131
4132 The partition name can only be set on certain types of partition
4133 table.  This works on C<gpt> but not on C<mbr> partitions.");
4134
4135   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4136    [], (* XXX Add a regression test for this. *)
4137    "list partitions on a device",
4138    "\
4139 This command parses the partition table on C<device> and
4140 returns the list of partitions found.
4141
4142 The fields in the returned structure are:
4143
4144 =over 4
4145
4146 =item B<part_num>
4147
4148 Partition number, counting from 1.
4149
4150 =item B<part_start>
4151
4152 Start of the partition I<in bytes>.  To get sectors you have to
4153 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4154
4155 =item B<part_end>
4156
4157 End of the partition in bytes.
4158
4159 =item B<part_size>
4160
4161 Size of the partition in bytes.
4162
4163 =back");
4164
4165   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4166    [InitEmpty, Always, TestOutput (
4167       [["part_disk"; "/dev/sda"; "gpt"];
4168        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4169    "get the partition table type",
4170    "\
4171 This command examines the partition table on C<device> and
4172 returns the partition table type (format) being used.
4173
4174 Common return values include: C<msdos> (a DOS/Windows style MBR
4175 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4176 values are possible, although unusual.  See C<guestfs_part_init>
4177 for a full list.");
4178
4179   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4180    [InitBasicFS, Always, TestOutputBuffer (
4181       [["fill"; "0x63"; "10"; "/test"];
4182        ["read_file"; "/test"]], "cccccccccc")],
4183    "fill a file with octets",
4184    "\
4185 This command creates a new file called C<path>.  The initial
4186 content of the file is C<len> octets of C<c>, where C<c>
4187 must be a number in the range C<[0..255]>.
4188
4189 To fill a file with zero bytes (sparsely), it is
4190 much more efficient to use C<guestfs_truncate_size>.");
4191
4192   ("available", (RErr, [StringList "groups"]), 216, [],
4193    [InitNone, Always, TestRun [["available"; ""]]],
4194    "test availability of some parts of the API",
4195    "\
4196 This command is used to check the availability of some
4197 groups of functionality in the appliance, which not all builds of
4198 the libguestfs appliance will be able to provide.
4199
4200 The libguestfs groups, and the functions that those
4201 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4202
4203 The argument C<groups> is a list of group names, eg:
4204 C<[\"inotify\", \"augeas\"]> would check for the availability of
4205 the Linux inotify functions and Augeas (configuration file
4206 editing) functions.
4207
4208 The command returns no error if I<all> requested groups are available.
4209
4210 It fails with an error if one or more of the requested
4211 groups is unavailable in the appliance.
4212
4213 If an unknown group name is included in the
4214 list of groups then an error is always returned.
4215
4216 I<Notes:>
4217
4218 =over 4
4219
4220 =item *
4221
4222 You must call C<guestfs_launch> before calling this function.
4223
4224 The reason is because we don't know what groups are
4225 supported by the appliance/daemon until it is running and can
4226 be queried.
4227
4228 =item *
4229
4230 If a group of functions is available, this does not necessarily
4231 mean that they will work.  You still have to check for errors
4232 when calling individual API functions even if they are
4233 available.
4234
4235 =item *
4236
4237 It is usually the job of distro packagers to build
4238 complete functionality into the libguestfs appliance.
4239 Upstream libguestfs, if built from source with all
4240 requirements satisfied, will support everything.
4241
4242 =item *
4243
4244 This call was added in version C<1.0.80>.  In previous
4245 versions of libguestfs all you could do would be to speculatively
4246 execute a command to find out if the daemon implemented it.
4247 See also C<guestfs_version>.
4248
4249 =back");
4250
4251   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4252    [InitBasicFS, Always, TestOutputBuffer (
4253       [["write_file"; "/src"; "hello, world"; "0"];
4254        ["dd"; "/src"; "/dest"];
4255        ["read_file"; "/dest"]], "hello, world")],
4256    "copy from source to destination using dd",
4257    "\
4258 This command copies from one source device or file C<src>
4259 to another destination device or file C<dest>.  Normally you
4260 would use this to copy to or from a device or partition, for
4261 example to duplicate a filesystem.
4262
4263 If the destination is a device, it must be as large or larger
4264 than the source file or device, otherwise the copy will fail.
4265 This command cannot do partial copies (see C<guestfs_copy_size>).");
4266
4267   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4268    [InitBasicFS, Always, TestOutputInt (
4269       [["write_file"; "/file"; "hello, world"; "0"];
4270        ["filesize"; "/file"]], 12)],
4271    "return the size of the file in bytes",
4272    "\
4273 This command returns the size of C<file> in bytes.
4274
4275 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4276 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4277 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4278
4279   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4280    [InitBasicFSonLVM, Always, TestOutputList (
4281       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4282        ["lvs"]], ["/dev/VG/LV2"])],
4283    "rename an LVM logical volume",
4284    "\
4285 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4286
4287   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4288    [InitBasicFSonLVM, Always, TestOutputList (
4289       [["umount"; "/"];
4290        ["vg_activate"; "false"; "VG"];
4291        ["vgrename"; "VG"; "VG2"];
4292        ["vg_activate"; "true"; "VG2"];
4293        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4294        ["vgs"]], ["VG2"])],
4295    "rename an LVM volume group",
4296    "\
4297 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4298
4299   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4300    [InitISOFS, Always, TestOutputBuffer (
4301       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4302    "list the contents of a single file in an initrd",
4303    "\
4304 This command unpacks the file C<filename> from the initrd file
4305 called C<initrdpath>.  The filename must be given I<without> the
4306 initial C</> character.
4307
4308 For example, in guestfish you could use the following command
4309 to examine the boot script (usually called C</init>)
4310 contained in a Linux initrd or initramfs image:
4311
4312  initrd-cat /boot/initrd-<version>.img init
4313
4314 See also C<guestfs_initrd_list>.");
4315
4316   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4317    [],
4318    "get the UUID of a physical volume",
4319    "\
4320 This command returns the UUID of the LVM PV C<device>.");
4321
4322   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4323    [],
4324    "get the UUID of a volume group",
4325    "\
4326 This command returns the UUID of the LVM VG named C<vgname>.");
4327
4328   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4329    [],
4330    "get the UUID of a logical volume",
4331    "\
4332 This command returns the UUID of the LVM LV C<device>.");
4333
4334   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4335    [],
4336    "get the PV UUIDs containing the volume group",
4337    "\
4338 Given a VG called C<vgname>, this returns the UUIDs of all
4339 the physical volumes that this volume group resides on.
4340
4341 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4342 calls to associate physical volumes and volume groups.
4343
4344 See also C<guestfs_vglvuuids>.");
4345
4346   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4347    [],
4348    "get the LV UUIDs of all LVs in the volume group",
4349    "\
4350 Given a VG called C<vgname>, this returns the UUIDs of all
4351 the logical volumes created in this volume group.
4352
4353 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4354 calls to associate logical volumes and volume groups.
4355
4356 See also C<guestfs_vgpvuuids>.");
4357
4358   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4359    [InitBasicFS, Always, TestOutputBuffer (
4360       [["write_file"; "/src"; "hello, world"; "0"];
4361        ["copy_size"; "/src"; "/dest"; "5"];
4362        ["read_file"; "/dest"]], "hello")],
4363    "copy size bytes from source to destination using dd",
4364    "\
4365 This command copies exactly C<size> bytes from one source device
4366 or file C<src> to another destination device or file C<dest>.
4367
4368 Note this will fail if the source is too short or if the destination
4369 is not large enough.");
4370
4371   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4372    [InitEmpty, Always, TestRun (
4373       [["part_init"; "/dev/sda"; "mbr"];
4374        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4375        ["part_del"; "/dev/sda"; "1"]])],
4376    "delete a partition",
4377    "\
4378 This command deletes the partition numbered C<partnum> on C<device>.
4379
4380 Note that in the case of MBR partitioning, deleting an
4381 extended partition also deletes any logical partitions
4382 it contains.");
4383
4384   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4385    [InitEmpty, Always, TestOutputTrue (
4386       [["part_init"; "/dev/sda"; "mbr"];
4387        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4388        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4389        ["part_get_bootable"; "/dev/sda"; "1"]])],
4390    "return true if a partition is bootable",
4391    "\
4392 This command returns true if the partition C<partnum> on
4393 C<device> has the bootable flag set.
4394
4395 See also C<guestfs_part_set_bootable>.");
4396
4397   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4398    [InitEmpty, Always, TestOutputInt (
4399       [["part_init"; "/dev/sda"; "mbr"];
4400        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4401        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4402        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4403    "get the MBR type byte (ID byte) from a partition",
4404    "\
4405 Returns the MBR type byte (also known as the ID byte) from
4406 the numbered partition C<partnum>.
4407
4408 Note that only MBR (old DOS-style) partitions have type bytes.
4409 You will get undefined results for other partition table
4410 types (see C<guestfs_part_get_parttype>).");
4411
4412   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4413    [], (* tested by part_get_mbr_id *)
4414    "set the MBR type byte (ID byte) of a partition",
4415    "\
4416 Sets the MBR type byte (also known as the ID byte) of
4417 the numbered partition C<partnum> to C<idbyte>.  Note
4418 that the type bytes quoted in most documentation are
4419 in fact hexadecimal numbers, but usually documented
4420 without any leading \"0x\" which might be confusing.
4421
4422 Note that only MBR (old DOS-style) partitions have type bytes.
4423 You will get undefined results for other partition table
4424 types (see C<guestfs_part_get_parttype>).");
4425
4426 ]
4427
4428 let all_functions = non_daemon_functions @ daemon_functions
4429
4430 (* In some places we want the functions to be displayed sorted
4431  * alphabetically, so this is useful:
4432  *)
4433 let all_functions_sorted =
4434   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4435                compare n1 n2) all_functions
4436
4437 (* Field types for structures. *)
4438 type field =
4439   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4440   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4441   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4442   | FUInt32
4443   | FInt32
4444   | FUInt64
4445   | FInt64
4446   | FBytes                      (* Any int measure that counts bytes. *)
4447   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4448   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4449
4450 (* Because we generate extra parsing code for LVM command line tools,
4451  * we have to pull out the LVM columns separately here.
4452  *)
4453 let lvm_pv_cols = [
4454   "pv_name", FString;
4455   "pv_uuid", FUUID;
4456   "pv_fmt", FString;
4457   "pv_size", FBytes;
4458   "dev_size", FBytes;
4459   "pv_free", FBytes;
4460   "pv_used", FBytes;
4461   "pv_attr", FString (* XXX *);
4462   "pv_pe_count", FInt64;
4463   "pv_pe_alloc_count", FInt64;
4464   "pv_tags", FString;
4465   "pe_start", FBytes;
4466   "pv_mda_count", FInt64;
4467   "pv_mda_free", FBytes;
4468   (* Not in Fedora 10:
4469      "pv_mda_size", FBytes;
4470   *)
4471 ]
4472 let lvm_vg_cols = [
4473   "vg_name", FString;
4474   "vg_uuid", FUUID;
4475   "vg_fmt", FString;
4476   "vg_attr", FString (* XXX *);
4477   "vg_size", FBytes;
4478   "vg_free", FBytes;
4479   "vg_sysid", FString;
4480   "vg_extent_size", FBytes;
4481   "vg_extent_count", FInt64;
4482   "vg_free_count", FInt64;
4483   "max_lv", FInt64;
4484   "max_pv", FInt64;
4485   "pv_count", FInt64;
4486   "lv_count", FInt64;
4487   "snap_count", FInt64;
4488   "vg_seqno", FInt64;
4489   "vg_tags", FString;
4490   "vg_mda_count", FInt64;
4491   "vg_mda_free", FBytes;
4492   (* Not in Fedora 10:
4493      "vg_mda_size", FBytes;
4494   *)
4495 ]
4496 let lvm_lv_cols = [
4497   "lv_name", FString;
4498   "lv_uuid", FUUID;
4499   "lv_attr", FString (* XXX *);
4500   "lv_major", FInt64;
4501   "lv_minor", FInt64;
4502   "lv_kernel_major", FInt64;
4503   "lv_kernel_minor", FInt64;
4504   "lv_size", FBytes;
4505   "seg_count", FInt64;
4506   "origin", FString;
4507   "snap_percent", FOptPercent;
4508   "copy_percent", FOptPercent;
4509   "move_pv", FString;
4510   "lv_tags", FString;
4511   "mirror_log", FString;
4512   "modules", FString;
4513 ]
4514
4515 (* Names and fields in all structures (in RStruct and RStructList)
4516  * that we support.
4517  *)
4518 let structs = [
4519   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4520    * not use this struct in any new code.
4521    *)
4522   "int_bool", [
4523     "i", FInt32;                (* for historical compatibility *)
4524     "b", FInt32;                (* for historical compatibility *)
4525   ];
4526
4527   (* LVM PVs, VGs, LVs. *)
4528   "lvm_pv", lvm_pv_cols;
4529   "lvm_vg", lvm_vg_cols;
4530   "lvm_lv", lvm_lv_cols;
4531
4532   (* Column names and types from stat structures.
4533    * NB. Can't use things like 'st_atime' because glibc header files
4534    * define some of these as macros.  Ugh.
4535    *)
4536   "stat", [
4537     "dev", FInt64;
4538     "ino", FInt64;
4539     "mode", FInt64;
4540     "nlink", FInt64;
4541     "uid", FInt64;
4542     "gid", FInt64;
4543     "rdev", FInt64;
4544     "size", FInt64;
4545     "blksize", FInt64;
4546     "blocks", FInt64;
4547     "atime", FInt64;
4548     "mtime", FInt64;
4549     "ctime", FInt64;
4550   ];
4551   "statvfs", [
4552     "bsize", FInt64;
4553     "frsize", FInt64;
4554     "blocks", FInt64;
4555     "bfree", FInt64;
4556     "bavail", FInt64;
4557     "files", FInt64;
4558     "ffree", FInt64;
4559     "favail", FInt64;
4560     "fsid", FInt64;
4561     "flag", FInt64;
4562     "namemax", FInt64;
4563   ];
4564
4565   (* Column names in dirent structure. *)
4566   "dirent", [
4567     "ino", FInt64;
4568     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4569     "ftyp", FChar;
4570     "name", FString;
4571   ];
4572
4573   (* Version numbers. *)
4574   "version", [
4575     "major", FInt64;
4576     "minor", FInt64;
4577     "release", FInt64;
4578     "extra", FString;
4579   ];
4580
4581   (* Extended attribute. *)
4582   "xattr", [
4583     "attrname", FString;
4584     "attrval", FBuffer;
4585   ];
4586
4587   (* Inotify events. *)
4588   "inotify_event", [
4589     "in_wd", FInt64;
4590     "in_mask", FUInt32;
4591     "in_cookie", FUInt32;
4592     "in_name", FString;
4593   ];
4594
4595   (* Partition table entry. *)
4596   "partition", [
4597     "part_num", FInt32;
4598     "part_start", FBytes;
4599     "part_end", FBytes;
4600     "part_size", FBytes;
4601   ];
4602 ] (* end of structs *)
4603
4604 (* Ugh, Java has to be different ..
4605  * These names are also used by the Haskell bindings.
4606  *)
4607 let java_structs = [
4608   "int_bool", "IntBool";
4609   "lvm_pv", "PV";
4610   "lvm_vg", "VG";
4611   "lvm_lv", "LV";
4612   "stat", "Stat";
4613   "statvfs", "StatVFS";
4614   "dirent", "Dirent";
4615   "version", "Version";
4616   "xattr", "XAttr";
4617   "inotify_event", "INotifyEvent";
4618   "partition", "Partition";
4619 ]
4620
4621 (* What structs are actually returned. *)
4622 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4623
4624 (* Returns a list of RStruct/RStructList structs that are returned
4625  * by any function.  Each element of returned list is a pair:
4626  *
4627  * (structname, RStructOnly)
4628  *    == there exists function which returns RStruct (_, structname)
4629  * (structname, RStructListOnly)
4630  *    == there exists function which returns RStructList (_, structname)
4631  * (structname, RStructAndList)
4632  *    == there are functions returning both RStruct (_, structname)
4633  *                                      and RStructList (_, structname)
4634  *)
4635 let rstructs_used_by functions =
4636   (* ||| is a "logical OR" for rstructs_used_t *)
4637   let (|||) a b =
4638     match a, b with
4639     | RStructAndList, _
4640     | _, RStructAndList -> RStructAndList
4641     | RStructOnly, RStructListOnly
4642     | RStructListOnly, RStructOnly -> RStructAndList
4643     | RStructOnly, RStructOnly -> RStructOnly
4644     | RStructListOnly, RStructListOnly -> RStructListOnly
4645   in
4646
4647   let h = Hashtbl.create 13 in
4648
4649   (* if elem->oldv exists, update entry using ||| operator,
4650    * else just add elem->newv to the hash
4651    *)
4652   let update elem newv =
4653     try  let oldv = Hashtbl.find h elem in
4654          Hashtbl.replace h elem (newv ||| oldv)
4655     with Not_found -> Hashtbl.add h elem newv
4656   in
4657
4658   List.iter (
4659     fun (_, style, _, _, _, _, _) ->
4660       match fst style with
4661       | RStruct (_, structname) -> update structname RStructOnly
4662       | RStructList (_, structname) -> update structname RStructListOnly
4663       | _ -> ()
4664   ) functions;
4665
4666   (* return key->values as a list of (key,value) *)
4667   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4668
4669 (* Used for testing language bindings. *)
4670 type callt =
4671   | CallString of string
4672   | CallOptString of string option
4673   | CallStringList of string list
4674   | CallInt of int
4675   | CallInt64 of int64
4676   | CallBool of bool
4677
4678 (* Used to memoize the result of pod2text. *)
4679 let pod2text_memo_filename = "src/.pod2text.data"
4680 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4681   try
4682     let chan = open_in pod2text_memo_filename in
4683     let v = input_value chan in
4684     close_in chan;
4685     v
4686   with
4687     _ -> Hashtbl.create 13
4688 let pod2text_memo_updated () =
4689   let chan = open_out pod2text_memo_filename in
4690   output_value chan pod2text_memo;
4691   close_out chan
4692
4693 (* Useful functions.
4694  * Note we don't want to use any external OCaml libraries which
4695  * makes this a bit harder than it should be.
4696  *)
4697 module StringMap = Map.Make (String)
4698
4699 let failwithf fs = ksprintf failwith fs
4700
4701 let unique = let i = ref 0 in fun () -> incr i; !i
4702
4703 let replace_char s c1 c2 =
4704   let s2 = String.copy s in
4705   let r = ref false in
4706   for i = 0 to String.length s2 - 1 do
4707     if String.unsafe_get s2 i = c1 then (
4708       String.unsafe_set s2 i c2;
4709       r := true
4710     )
4711   done;
4712   if not !r then s else s2
4713
4714 let isspace c =
4715   c = ' '
4716   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4717
4718 let triml ?(test = isspace) str =
4719   let i = ref 0 in
4720   let n = ref (String.length str) in
4721   while !n > 0 && test str.[!i]; do
4722     decr n;
4723     incr i
4724   done;
4725   if !i = 0 then str
4726   else String.sub str !i !n
4727
4728 let trimr ?(test = isspace) str =
4729   let n = ref (String.length str) in
4730   while !n > 0 && test str.[!n-1]; do
4731     decr n
4732   done;
4733   if !n = String.length str then str
4734   else String.sub str 0 !n
4735
4736 let trim ?(test = isspace) str =
4737   trimr ~test (triml ~test str)
4738
4739 let rec find s sub =
4740   let len = String.length s in
4741   let sublen = String.length sub in
4742   let rec loop i =
4743     if i <= len-sublen then (
4744       let rec loop2 j =
4745         if j < sublen then (
4746           if s.[i+j] = sub.[j] then loop2 (j+1)
4747           else -1
4748         ) else
4749           i (* found *)
4750       in
4751       let r = loop2 0 in
4752       if r = -1 then loop (i+1) else r
4753     ) else
4754       -1 (* not found *)
4755   in
4756   loop 0
4757
4758 let rec replace_str s s1 s2 =
4759   let len = String.length s in
4760   let sublen = String.length s1 in
4761   let i = find s s1 in
4762   if i = -1 then s
4763   else (
4764     let s' = String.sub s 0 i in
4765     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4766     s' ^ s2 ^ replace_str s'' s1 s2
4767   )
4768
4769 let rec string_split sep str =
4770   let len = String.length str in
4771   let seplen = String.length sep in
4772   let i = find str sep in
4773   if i = -1 then [str]
4774   else (
4775     let s' = String.sub str 0 i in
4776     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4777     s' :: string_split sep s''
4778   )
4779
4780 let files_equal n1 n2 =
4781   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4782   match Sys.command cmd with
4783   | 0 -> true
4784   | 1 -> false
4785   | i -> failwithf "%s: failed with error code %d" cmd i
4786
4787 let rec filter_map f = function
4788   | [] -> []
4789   | x :: xs ->
4790       match f x with
4791       | Some y -> y :: filter_map f xs
4792       | None -> filter_map f xs
4793
4794 let rec find_map f = function
4795   | [] -> raise Not_found
4796   | x :: xs ->
4797       match f x with
4798       | Some y -> y
4799       | None -> find_map f xs
4800
4801 let iteri f xs =
4802   let rec loop i = function
4803     | [] -> ()
4804     | x :: xs -> f i x; loop (i+1) xs
4805   in
4806   loop 0 xs
4807
4808 let mapi f xs =
4809   let rec loop i = function
4810     | [] -> []
4811     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4812   in
4813   loop 0 xs
4814
4815 let count_chars c str =
4816   let count = ref 0 in
4817   for i = 0 to String.length str - 1 do
4818     if c = String.unsafe_get str i then incr count
4819   done;
4820   !count
4821
4822 let name_of_argt = function
4823   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4824   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4825   | FileIn n | FileOut n -> n
4826
4827 let java_name_of_struct typ =
4828   try List.assoc typ java_structs
4829   with Not_found ->
4830     failwithf
4831       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4832
4833 let cols_of_struct typ =
4834   try List.assoc typ structs
4835   with Not_found ->
4836     failwithf "cols_of_struct: unknown struct %s" typ
4837
4838 let seq_of_test = function
4839   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4840   | TestOutputListOfDevices (s, _)
4841   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4842   | TestOutputTrue s | TestOutputFalse s
4843   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4844   | TestOutputStruct (s, _)
4845   | TestLastFail s -> s
4846
4847 (* Handling for function flags. *)
4848 let protocol_limit_warning =
4849   "Because of the message protocol, there is a transfer limit
4850 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4851
4852 let danger_will_robinson =
4853   "B<This command is dangerous.  Without careful use you
4854 can easily destroy all your data>."
4855
4856 let deprecation_notice flags =
4857   try
4858     let alt =
4859       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4860     let txt =
4861       sprintf "This function is deprecated.
4862 In new code, use the C<%s> call instead.
4863
4864 Deprecated functions will not be removed from the API, but the
4865 fact that they are deprecated indicates that there are problems
4866 with correct use of these functions." alt in
4867     Some txt
4868   with
4869     Not_found -> None
4870
4871 (* Create list of optional groups. *)
4872 let optgroups =
4873   let h = Hashtbl.create 13 in
4874   List.iter (
4875     fun (name, _, _, flags, _, _, _) ->
4876       List.iter (
4877         function
4878         | Optional group ->
4879             let names = try Hashtbl.find h group with Not_found -> [] in
4880             Hashtbl.replace h group (name :: names)
4881         | _ -> ()
4882       ) flags
4883   ) daemon_functions;
4884   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4885   let groups =
4886     List.map (
4887       fun group -> group, List.sort compare (Hashtbl.find h group)
4888     ) groups in
4889   List.sort (fun x y -> compare (fst x) (fst y)) groups
4890
4891 (* Check function names etc. for consistency. *)
4892 let check_functions () =
4893   let contains_uppercase str =
4894     let len = String.length str in
4895     let rec loop i =
4896       if i >= len then false
4897       else (
4898         let c = str.[i] in
4899         if c >= 'A' && c <= 'Z' then true
4900         else loop (i+1)
4901       )
4902     in
4903     loop 0
4904   in
4905
4906   (* Check function names. *)
4907   List.iter (
4908     fun (name, _, _, _, _, _, _) ->
4909       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4910         failwithf "function name %s does not need 'guestfs' prefix" name;
4911       if name = "" then
4912         failwithf "function name is empty";
4913       if name.[0] < 'a' || name.[0] > 'z' then
4914         failwithf "function name %s must start with lowercase a-z" name;
4915       if String.contains name '-' then
4916         failwithf "function name %s should not contain '-', use '_' instead."
4917           name
4918   ) all_functions;
4919
4920   (* Check function parameter/return names. *)
4921   List.iter (
4922     fun (name, style, _, _, _, _, _) ->
4923       let check_arg_ret_name n =
4924         if contains_uppercase n then
4925           failwithf "%s param/ret %s should not contain uppercase chars"
4926             name n;
4927         if String.contains n '-' || String.contains n '_' then
4928           failwithf "%s param/ret %s should not contain '-' or '_'"
4929             name n;
4930         if n = "value" then
4931           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;
4932         if n = "int" || n = "char" || n = "short" || n = "long" then
4933           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4934         if n = "i" || n = "n" then
4935           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4936         if n = "argv" || n = "args" then
4937           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4938
4939         (* List Haskell, OCaml and C keywords here.
4940          * http://www.haskell.org/haskellwiki/Keywords
4941          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4942          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4943          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4944          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4945          * Omitting _-containing words, since they're handled above.
4946          * Omitting the OCaml reserved word, "val", is ok,
4947          * and saves us from renaming several parameters.
4948          *)
4949         let reserved = [
4950           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4951           "char"; "class"; "const"; "constraint"; "continue"; "data";
4952           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4953           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4954           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4955           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4956           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4957           "interface";
4958           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4959           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4960           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4961           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4962           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4963           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4964           "volatile"; "when"; "where"; "while";
4965           ] in
4966         if List.mem n reserved then
4967           failwithf "%s has param/ret using reserved word %s" name n;
4968       in
4969
4970       (match fst style with
4971        | RErr -> ()
4972        | RInt n | RInt64 n | RBool n
4973        | RConstString n | RConstOptString n | RString n
4974        | RStringList n | RStruct (n, _) | RStructList (n, _)
4975        | RHashtable n | RBufferOut n ->
4976            check_arg_ret_name n
4977       );
4978       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4979   ) all_functions;
4980
4981   (* Check short descriptions. *)
4982   List.iter (
4983     fun (name, _, _, _, _, shortdesc, _) ->
4984       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4985         failwithf "short description of %s should begin with lowercase." name;
4986       let c = shortdesc.[String.length shortdesc-1] in
4987       if c = '\n' || c = '.' then
4988         failwithf "short description of %s should not end with . or \\n." name
4989   ) all_functions;
4990
4991   (* Check long descriptions. *)
4992   List.iter (
4993     fun (name, _, _, _, _, _, longdesc) ->
4994       if longdesc.[String.length longdesc-1] = '\n' then
4995         failwithf "long description of %s should not end with \\n." name
4996   ) all_functions;
4997
4998   (* Check proc_nrs. *)
4999   List.iter (
5000     fun (name, _, proc_nr, _, _, _, _) ->
5001       if proc_nr <= 0 then
5002         failwithf "daemon function %s should have proc_nr > 0" name
5003   ) daemon_functions;
5004
5005   List.iter (
5006     fun (name, _, proc_nr, _, _, _, _) ->
5007       if proc_nr <> -1 then
5008         failwithf "non-daemon function %s should have proc_nr -1" name
5009   ) non_daemon_functions;
5010
5011   let proc_nrs =
5012     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5013       daemon_functions in
5014   let proc_nrs =
5015     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5016   let rec loop = function
5017     | [] -> ()
5018     | [_] -> ()
5019     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5020         loop rest
5021     | (name1,nr1) :: (name2,nr2) :: _ ->
5022         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5023           name1 name2 nr1 nr2
5024   in
5025   loop proc_nrs;
5026
5027   (* Check tests. *)
5028   List.iter (
5029     function
5030       (* Ignore functions that have no tests.  We generate a
5031        * warning when the user does 'make check' instead.
5032        *)
5033     | name, _, _, _, [], _, _ -> ()
5034     | name, _, _, _, tests, _, _ ->
5035         let funcs =
5036           List.map (
5037             fun (_, _, test) ->
5038               match seq_of_test test with
5039               | [] ->
5040                   failwithf "%s has a test containing an empty sequence" name
5041               | cmds -> List.map List.hd cmds
5042           ) tests in
5043         let funcs = List.flatten funcs in
5044
5045         let tested = List.mem name funcs in
5046
5047         if not tested then
5048           failwithf "function %s has tests but does not test itself" name
5049   ) all_functions
5050
5051 (* 'pr' prints to the current output file. *)
5052 let chan = ref Pervasives.stdout
5053 let lines = ref 0
5054 let pr fs =
5055   ksprintf
5056     (fun str ->
5057        let i = count_chars '\n' str in
5058        lines := !lines + i;
5059        output_string !chan str
5060     ) fs
5061
5062 let copyright_years =
5063   let this_year = 1900 + (localtime (time ())).tm_year in
5064   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5065
5066 (* Generate a header block in a number of standard styles. *)
5067 type comment_style =
5068     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5069 type license = GPLv2plus | LGPLv2plus
5070
5071 let generate_header ?(extra_inputs = []) comment license =
5072   let inputs = "src/generator.ml" :: extra_inputs in
5073   let c = match comment with
5074     | CStyle ->         pr "/* "; " *"
5075     | CPlusPlusStyle -> pr "// "; "//"
5076     | HashStyle ->      pr "# ";  "#"
5077     | OCamlStyle ->     pr "(* "; " *"
5078     | HaskellStyle ->   pr "{- "; "  " in
5079   pr "libguestfs generated file\n";
5080   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5081   List.iter (pr "%s   %s\n" c) inputs;
5082   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5083   pr "%s\n" c;
5084   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5085   pr "%s\n" c;
5086   (match license with
5087    | GPLv2plus ->
5088        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5089        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5090        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5091        pr "%s (at your option) any later version.\n" c;
5092        pr "%s\n" c;
5093        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5094        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5095        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5096        pr "%s GNU General Public License for more details.\n" c;
5097        pr "%s\n" c;
5098        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5099        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5100        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5101
5102    | LGPLv2plus ->
5103        pr "%s This library is free software; you can redistribute it and/or\n" c;
5104        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5105        pr "%s License as published by the Free Software Foundation; either\n" c;
5106        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5107        pr "%s\n" c;
5108        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5109        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5110        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5111        pr "%s Lesser General Public License for more details.\n" c;
5112        pr "%s\n" c;
5113        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5114        pr "%s License along with this library; if not, write to the Free Software\n" c;
5115        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5116   );
5117   (match comment with
5118    | CStyle -> pr " */\n"
5119    | CPlusPlusStyle
5120    | HashStyle -> ()
5121    | OCamlStyle -> pr " *)\n"
5122    | HaskellStyle -> pr "-}\n"
5123   );
5124   pr "\n"
5125
5126 (* Start of main code generation functions below this line. *)
5127
5128 (* Generate the pod documentation for the C API. *)
5129 let rec generate_actions_pod () =
5130   List.iter (
5131     fun (shortname, style, _, flags, _, _, longdesc) ->
5132       if not (List.mem NotInDocs flags) then (
5133         let name = "guestfs_" ^ shortname in
5134         pr "=head2 %s\n\n" name;
5135         pr " ";
5136         generate_prototype ~extern:false ~handle:"g" name style;
5137         pr "\n\n";
5138         pr "%s\n\n" longdesc;
5139         (match fst style with
5140          | RErr ->
5141              pr "This function returns 0 on success or -1 on error.\n\n"
5142          | RInt _ ->
5143              pr "On error this function returns -1.\n\n"
5144          | RInt64 _ ->
5145              pr "On error this function returns -1.\n\n"
5146          | RBool _ ->
5147              pr "This function returns a C truth value on success or -1 on error.\n\n"
5148          | RConstString _ ->
5149              pr "This function returns a string, or NULL on error.
5150 The string is owned by the guest handle and must I<not> be freed.\n\n"
5151          | RConstOptString _ ->
5152              pr "This function returns a string which may be NULL.
5153 There is way to return an error from this function.
5154 The string is owned by the guest handle and must I<not> be freed.\n\n"
5155          | RString _ ->
5156              pr "This function returns a string, or NULL on error.
5157 I<The caller must free the returned string after use>.\n\n"
5158          | RStringList _ ->
5159              pr "This function returns a NULL-terminated array of strings
5160 (like L<environ(3)>), or NULL if there was an error.
5161 I<The caller must free the strings and the array after use>.\n\n"
5162          | RStruct (_, typ) ->
5163              pr "This function returns a C<struct guestfs_%s *>,
5164 or NULL if there was an error.
5165 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5166          | RStructList (_, typ) ->
5167              pr "This function returns a C<struct guestfs_%s_list *>
5168 (see E<lt>guestfs-structs.hE<gt>),
5169 or NULL if there was an error.
5170 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5171          | RHashtable _ ->
5172              pr "This function returns a NULL-terminated array of
5173 strings, or NULL if there was an error.
5174 The array of strings will always have length C<2n+1>, where
5175 C<n> keys and values alternate, followed by the trailing NULL entry.
5176 I<The caller must free the strings and the array after use>.\n\n"
5177          | RBufferOut _ ->
5178              pr "This function returns a buffer, or NULL on error.
5179 The size of the returned buffer is written to C<*size_r>.
5180 I<The caller must free the returned buffer after use>.\n\n"
5181         );
5182         if List.mem ProtocolLimitWarning flags then
5183           pr "%s\n\n" protocol_limit_warning;
5184         if List.mem DangerWillRobinson flags then
5185           pr "%s\n\n" danger_will_robinson;
5186         match deprecation_notice flags with
5187         | None -> ()
5188         | Some txt -> pr "%s\n\n" txt
5189       )
5190   ) all_functions_sorted
5191
5192 and generate_structs_pod () =
5193   (* Structs documentation. *)
5194   List.iter (
5195     fun (typ, cols) ->
5196       pr "=head2 guestfs_%s\n" typ;
5197       pr "\n";
5198       pr " struct guestfs_%s {\n" typ;
5199       List.iter (
5200         function
5201         | name, FChar -> pr "   char %s;\n" name
5202         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5203         | name, FInt32 -> pr "   int32_t %s;\n" name
5204         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5205         | name, FInt64 -> pr "   int64_t %s;\n" name
5206         | name, FString -> pr "   char *%s;\n" name
5207         | name, FBuffer ->
5208             pr "   /* The next two fields describe a byte array. */\n";
5209             pr "   uint32_t %s_len;\n" name;
5210             pr "   char *%s;\n" name
5211         | name, FUUID ->
5212             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5213             pr "   char %s[32];\n" name
5214         | name, FOptPercent ->
5215             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5216             pr "   float %s;\n" name
5217       ) cols;
5218       pr " };\n";
5219       pr " \n";
5220       pr " struct guestfs_%s_list {\n" typ;
5221       pr "   uint32_t len; /* Number of elements in list. */\n";
5222       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5223       pr " };\n";
5224       pr " \n";
5225       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5226       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5227         typ typ;
5228       pr "\n"
5229   ) structs
5230
5231 and generate_availability_pod () =
5232   (* Availability documentation. *)
5233   pr "=over 4\n";
5234   pr "\n";
5235   List.iter (
5236     fun (group, functions) ->
5237       pr "=item B<%s>\n" group;
5238       pr "\n";
5239       pr "The following functions:\n";
5240       List.iter (pr "L</guestfs_%s>\n") functions;
5241       pr "\n"
5242   ) optgroups;
5243   pr "=back\n";
5244   pr "\n"
5245
5246 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5247  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5248  *
5249  * We have to use an underscore instead of a dash because otherwise
5250  * rpcgen generates incorrect code.
5251  *
5252  * This header is NOT exported to clients, but see also generate_structs_h.
5253  *)
5254 and generate_xdr () =
5255   generate_header CStyle LGPLv2plus;
5256
5257   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5258   pr "typedef string str<>;\n";
5259   pr "\n";
5260
5261   (* Internal structures. *)
5262   List.iter (
5263     function
5264     | typ, cols ->
5265         pr "struct guestfs_int_%s {\n" typ;
5266         List.iter (function
5267                    | name, FChar -> pr "  char %s;\n" name
5268                    | name, FString -> pr "  string %s<>;\n" name
5269                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5270                    | name, FUUID -> pr "  opaque %s[32];\n" name
5271                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5272                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5273                    | name, FOptPercent -> pr "  float %s;\n" name
5274                   ) cols;
5275         pr "};\n";
5276         pr "\n";
5277         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5278         pr "\n";
5279   ) structs;
5280
5281   List.iter (
5282     fun (shortname, style, _, _, _, _, _) ->
5283       let name = "guestfs_" ^ shortname in
5284
5285       (match snd style with
5286        | [] -> ()
5287        | args ->
5288            pr "struct %s_args {\n" name;
5289            List.iter (
5290              function
5291              | Pathname n | Device n | Dev_or_Path n | String n ->
5292                  pr "  string %s<>;\n" n
5293              | OptString n -> pr "  str *%s;\n" n
5294              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5295              | Bool n -> pr "  bool %s;\n" n
5296              | Int n -> pr "  int %s;\n" n
5297              | Int64 n -> pr "  hyper %s;\n" n
5298              | FileIn _ | FileOut _ -> ()
5299            ) args;
5300            pr "};\n\n"
5301       );
5302       (match fst style with
5303        | RErr -> ()
5304        | RInt n ->
5305            pr "struct %s_ret {\n" name;
5306            pr "  int %s;\n" n;
5307            pr "};\n\n"
5308        | RInt64 n ->
5309            pr "struct %s_ret {\n" name;
5310            pr "  hyper %s;\n" n;
5311            pr "};\n\n"
5312        | RBool n ->
5313            pr "struct %s_ret {\n" name;
5314            pr "  bool %s;\n" n;
5315            pr "};\n\n"
5316        | RConstString _ | RConstOptString _ ->
5317            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5318        | RString n ->
5319            pr "struct %s_ret {\n" name;
5320            pr "  string %s<>;\n" n;
5321            pr "};\n\n"
5322        | RStringList n ->
5323            pr "struct %s_ret {\n" name;
5324            pr "  str %s<>;\n" n;
5325            pr "};\n\n"
5326        | RStruct (n, typ) ->
5327            pr "struct %s_ret {\n" name;
5328            pr "  guestfs_int_%s %s;\n" typ n;
5329            pr "};\n\n"
5330        | RStructList (n, typ) ->
5331            pr "struct %s_ret {\n" name;
5332            pr "  guestfs_int_%s_list %s;\n" typ n;
5333            pr "};\n\n"
5334        | RHashtable n ->
5335            pr "struct %s_ret {\n" name;
5336            pr "  str %s<>;\n" n;
5337            pr "};\n\n"
5338        | RBufferOut n ->
5339            pr "struct %s_ret {\n" name;
5340            pr "  opaque %s<>;\n" n;
5341            pr "};\n\n"
5342       );
5343   ) daemon_functions;
5344
5345   (* Table of procedure numbers. *)
5346   pr "enum guestfs_procedure {\n";
5347   List.iter (
5348     fun (shortname, _, proc_nr, _, _, _, _) ->
5349       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5350   ) daemon_functions;
5351   pr "  GUESTFS_PROC_NR_PROCS\n";
5352   pr "};\n";
5353   pr "\n";
5354
5355   (* Having to choose a maximum message size is annoying for several
5356    * reasons (it limits what we can do in the API), but it (a) makes
5357    * the protocol a lot simpler, and (b) provides a bound on the size
5358    * of the daemon which operates in limited memory space.
5359    *)
5360   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5361   pr "\n";
5362
5363   (* Message header, etc. *)
5364   pr "\
5365 /* The communication protocol is now documented in the guestfs(3)
5366  * manpage.
5367  */
5368
5369 const GUESTFS_PROGRAM = 0x2000F5F5;
5370 const GUESTFS_PROTOCOL_VERSION = 1;
5371
5372 /* These constants must be larger than any possible message length. */
5373 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5374 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5375
5376 enum guestfs_message_direction {
5377   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5378   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5379 };
5380
5381 enum guestfs_message_status {
5382   GUESTFS_STATUS_OK = 0,
5383   GUESTFS_STATUS_ERROR = 1
5384 };
5385
5386 const GUESTFS_ERROR_LEN = 256;
5387
5388 struct guestfs_message_error {
5389   string error_message<GUESTFS_ERROR_LEN>;
5390 };
5391
5392 struct guestfs_message_header {
5393   unsigned prog;                     /* GUESTFS_PROGRAM */
5394   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5395   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5396   guestfs_message_direction direction;
5397   unsigned serial;                   /* message serial number */
5398   guestfs_message_status status;
5399 };
5400
5401 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5402
5403 struct guestfs_chunk {
5404   int cancel;                        /* if non-zero, transfer is cancelled */
5405   /* data size is 0 bytes if the transfer has finished successfully */
5406   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5407 };
5408 "
5409
5410 (* Generate the guestfs-structs.h file. *)
5411 and generate_structs_h () =
5412   generate_header CStyle LGPLv2plus;
5413
5414   (* This is a public exported header file containing various
5415    * structures.  The structures are carefully written to have
5416    * exactly the same in-memory format as the XDR structures that
5417    * we use on the wire to the daemon.  The reason for creating
5418    * copies of these structures here is just so we don't have to
5419    * export the whole of guestfs_protocol.h (which includes much
5420    * unrelated and XDR-dependent stuff that we don't want to be
5421    * public, or required by clients).
5422    *
5423    * To reiterate, we will pass these structures to and from the
5424    * client with a simple assignment or memcpy, so the format
5425    * must be identical to what rpcgen / the RFC defines.
5426    *)
5427
5428   (* Public structures. *)
5429   List.iter (
5430     fun (typ, cols) ->
5431       pr "struct guestfs_%s {\n" typ;
5432       List.iter (
5433         function
5434         | name, FChar -> pr "  char %s;\n" name
5435         | name, FString -> pr "  char *%s;\n" name
5436         | name, FBuffer ->
5437             pr "  uint32_t %s_len;\n" name;
5438             pr "  char *%s;\n" name
5439         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5440         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5441         | name, FInt32 -> pr "  int32_t %s;\n" name
5442         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5443         | name, FInt64 -> pr "  int64_t %s;\n" name
5444         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5445       ) cols;
5446       pr "};\n";
5447       pr "\n";
5448       pr "struct guestfs_%s_list {\n" typ;
5449       pr "  uint32_t len;\n";
5450       pr "  struct guestfs_%s *val;\n" typ;
5451       pr "};\n";
5452       pr "\n";
5453       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5454       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5455       pr "\n"
5456   ) structs
5457
5458 (* Generate the guestfs-actions.h file. *)
5459 and generate_actions_h () =
5460   generate_header CStyle LGPLv2plus;
5461   List.iter (
5462     fun (shortname, style, _, _, _, _, _) ->
5463       let name = "guestfs_" ^ shortname in
5464       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5465         name style
5466   ) all_functions
5467
5468 (* Generate the guestfs-internal-actions.h file. *)
5469 and generate_internal_actions_h () =
5470   generate_header CStyle LGPLv2plus;
5471   List.iter (
5472     fun (shortname, style, _, _, _, _, _) ->
5473       let name = "guestfs__" ^ shortname in
5474       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5475         name style
5476   ) non_daemon_functions
5477
5478 (* Generate the client-side dispatch stubs. *)
5479 and generate_client_actions () =
5480   generate_header CStyle LGPLv2plus;
5481
5482   pr "\
5483 #include <stdio.h>
5484 #include <stdlib.h>
5485 #include <stdint.h>
5486 #include <string.h>
5487 #include <inttypes.h>
5488
5489 #include \"guestfs.h\"
5490 #include \"guestfs-internal.h\"
5491 #include \"guestfs-internal-actions.h\"
5492 #include \"guestfs_protocol.h\"
5493
5494 #define error guestfs_error
5495 //#define perrorf guestfs_perrorf
5496 #define safe_malloc guestfs_safe_malloc
5497 #define safe_realloc guestfs_safe_realloc
5498 //#define safe_strdup guestfs_safe_strdup
5499 #define safe_memdup guestfs_safe_memdup
5500
5501 /* Check the return message from a call for validity. */
5502 static int
5503 check_reply_header (guestfs_h *g,
5504                     const struct guestfs_message_header *hdr,
5505                     unsigned int proc_nr, unsigned int serial)
5506 {
5507   if (hdr->prog != GUESTFS_PROGRAM) {
5508     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5509     return -1;
5510   }
5511   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5512     error (g, \"wrong protocol version (%%d/%%d)\",
5513            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5514     return -1;
5515   }
5516   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5517     error (g, \"unexpected message direction (%%d/%%d)\",
5518            hdr->direction, GUESTFS_DIRECTION_REPLY);
5519     return -1;
5520   }
5521   if (hdr->proc != proc_nr) {
5522     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5523     return -1;
5524   }
5525   if (hdr->serial != serial) {
5526     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5527     return -1;
5528   }
5529
5530   return 0;
5531 }
5532
5533 /* Check we are in the right state to run a high-level action. */
5534 static int
5535 check_state (guestfs_h *g, const char *caller)
5536 {
5537   if (!guestfs__is_ready (g)) {
5538     if (guestfs__is_config (g) || guestfs__is_launching (g))
5539       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5540         caller);
5541     else
5542       error (g, \"%%s called from the wrong state, %%d != READY\",
5543         caller, guestfs__get_state (g));
5544     return -1;
5545   }
5546   return 0;
5547 }
5548
5549 ";
5550
5551   (* Generate code to generate guestfish call traces. *)
5552   let trace_call shortname style =
5553     pr "  if (guestfs__get_trace (g)) {\n";
5554
5555     let needs_i =
5556       List.exists (function
5557                    | StringList _ | DeviceList _ -> true
5558                    | _ -> false) (snd style) in
5559     if needs_i then (
5560       pr "    int i;\n";
5561       pr "\n"
5562     );
5563
5564     pr "    printf (\"%s\");\n" shortname;
5565     List.iter (
5566       function
5567       | String n                        (* strings *)
5568       | Device n
5569       | Pathname n
5570       | Dev_or_Path n
5571       | FileIn n
5572       | FileOut n ->
5573           (* guestfish doesn't support string escaping, so neither do we *)
5574           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5575       | OptString n ->                  (* string option *)
5576           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5577           pr "    else printf (\" null\");\n"
5578       | StringList n
5579       | DeviceList n ->                 (* string list *)
5580           pr "    putchar (' ');\n";
5581           pr "    putchar ('\"');\n";
5582           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5583           pr "      if (i > 0) putchar (' ');\n";
5584           pr "      fputs (%s[i], stdout);\n" n;
5585           pr "    }\n";
5586           pr "    putchar ('\"');\n";
5587       | Bool n ->                       (* boolean *)
5588           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5589       | Int n ->                        (* int *)
5590           pr "    printf (\" %%d\", %s);\n" n
5591       | Int64 n ->
5592           pr "    printf (\" %%\" PRIi64, %s);\n" n
5593     ) (snd style);
5594     pr "    putchar ('\\n');\n";
5595     pr "  }\n";
5596     pr "\n";
5597   in
5598
5599   (* For non-daemon functions, generate a wrapper around each function. *)
5600   List.iter (
5601     fun (shortname, style, _, _, _, _, _) ->
5602       let name = "guestfs_" ^ shortname in
5603
5604       generate_prototype ~extern:false ~semicolon:false ~newline:true
5605         ~handle:"g" name style;
5606       pr "{\n";
5607       trace_call shortname style;
5608       pr "  return guestfs__%s " shortname;
5609       generate_c_call_args ~handle:"g" style;
5610       pr ";\n";
5611       pr "}\n";
5612       pr "\n"
5613   ) non_daemon_functions;
5614
5615   (* Client-side stubs for each function. *)
5616   List.iter (
5617     fun (shortname, style, _, _, _, _, _) ->
5618       let name = "guestfs_" ^ shortname in
5619
5620       (* Generate the action stub. *)
5621       generate_prototype ~extern:false ~semicolon:false ~newline:true
5622         ~handle:"g" name style;
5623
5624       let error_code =
5625         match fst style with
5626         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5627         | RConstString _ | RConstOptString _ ->
5628             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5629         | RString _ | RStringList _
5630         | RStruct _ | RStructList _
5631         | RHashtable _ | RBufferOut _ ->
5632             "NULL" in
5633
5634       pr "{\n";
5635
5636       (match snd style with
5637        | [] -> ()
5638        | _ -> pr "  struct %s_args args;\n" name
5639       );
5640
5641       pr "  guestfs_message_header hdr;\n";
5642       pr "  guestfs_message_error err;\n";
5643       let has_ret =
5644         match fst style with
5645         | RErr -> false
5646         | RConstString _ | RConstOptString _ ->
5647             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5648         | RInt _ | RInt64 _
5649         | RBool _ | RString _ | RStringList _
5650         | RStruct _ | RStructList _
5651         | RHashtable _ | RBufferOut _ ->
5652             pr "  struct %s_ret ret;\n" name;
5653             true in
5654
5655       pr "  int serial;\n";
5656       pr "  int r;\n";
5657       pr "\n";
5658       trace_call shortname style;
5659       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5660       pr "  guestfs___set_busy (g);\n";
5661       pr "\n";
5662
5663       (* Send the main header and arguments. *)
5664       (match snd style with
5665        | [] ->
5666            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5667              (String.uppercase shortname)
5668        | args ->
5669            List.iter (
5670              function
5671              | Pathname n | Device n | Dev_or_Path n | String n ->
5672                  pr "  args.%s = (char *) %s;\n" n n
5673              | OptString n ->
5674                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5675              | StringList n | DeviceList n ->
5676                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5677                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5678              | Bool n ->
5679                  pr "  args.%s = %s;\n" n n
5680              | Int n ->
5681                  pr "  args.%s = %s;\n" n n
5682              | Int64 n ->
5683                  pr "  args.%s = %s;\n" n n
5684              | FileIn _ | FileOut _ -> ()
5685            ) args;
5686            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5687              (String.uppercase shortname);
5688            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5689              name;
5690       );
5691       pr "  if (serial == -1) {\n";
5692       pr "    guestfs___end_busy (g);\n";
5693       pr "    return %s;\n" error_code;
5694       pr "  }\n";
5695       pr "\n";
5696
5697       (* Send any additional files (FileIn) requested. *)
5698       let need_read_reply_label = ref false in
5699       List.iter (
5700         function
5701         | FileIn n ->
5702             pr "  r = guestfs___send_file (g, %s);\n" n;
5703             pr "  if (r == -1) {\n";
5704             pr "    guestfs___end_busy (g);\n";
5705             pr "    return %s;\n" error_code;
5706             pr "  }\n";
5707             pr "  if (r == -2) /* daemon cancelled */\n";
5708             pr "    goto read_reply;\n";
5709             need_read_reply_label := true;
5710             pr "\n";
5711         | _ -> ()
5712       ) (snd style);
5713
5714       (* Wait for the reply from the remote end. *)
5715       if !need_read_reply_label then pr " read_reply:\n";
5716       pr "  memset (&hdr, 0, sizeof hdr);\n";
5717       pr "  memset (&err, 0, sizeof err);\n";
5718       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5719       pr "\n";
5720       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5721       if not has_ret then
5722         pr "NULL, NULL"
5723       else
5724         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5725       pr ");\n";
5726
5727       pr "  if (r == -1) {\n";
5728       pr "    guestfs___end_busy (g);\n";
5729       pr "    return %s;\n" error_code;
5730       pr "  }\n";
5731       pr "\n";
5732
5733       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5734         (String.uppercase shortname);
5735       pr "    guestfs___end_busy (g);\n";
5736       pr "    return %s;\n" error_code;
5737       pr "  }\n";
5738       pr "\n";
5739
5740       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5741       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5742       pr "    free (err.error_message);\n";
5743       pr "    guestfs___end_busy (g);\n";
5744       pr "    return %s;\n" error_code;
5745       pr "  }\n";
5746       pr "\n";
5747
5748       (* Expecting to receive further files (FileOut)? *)
5749       List.iter (
5750         function
5751         | FileOut n ->
5752             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5753             pr "    guestfs___end_busy (g);\n";
5754             pr "    return %s;\n" error_code;
5755             pr "  }\n";
5756             pr "\n";
5757         | _ -> ()
5758       ) (snd style);
5759
5760       pr "  guestfs___end_busy (g);\n";
5761
5762       (match fst style with
5763        | RErr -> pr "  return 0;\n"
5764        | RInt n | RInt64 n | RBool n ->
5765            pr "  return ret.%s;\n" n
5766        | RConstString _ | RConstOptString _ ->
5767            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5768        | RString n ->
5769            pr "  return ret.%s; /* caller will free */\n" n
5770        | RStringList n | RHashtable n ->
5771            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5772            pr "  ret.%s.%s_val =\n" n n;
5773            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5774            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5775              n n;
5776            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5777            pr "  return ret.%s.%s_val;\n" n n
5778        | RStruct (n, _) ->
5779            pr "  /* caller will free this */\n";
5780            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5781        | RStructList (n, _) ->
5782            pr "  /* caller will free this */\n";
5783            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5784        | RBufferOut n ->
5785            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5786            pr "   * _val might be NULL here.  To make the API saner for\n";
5787            pr "   * callers, we turn this case into a unique pointer (using\n";
5788            pr "   * malloc(1)).\n";
5789            pr "   */\n";
5790            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5791            pr "    *size_r = ret.%s.%s_len;\n" n n;
5792            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5793            pr "  } else {\n";
5794            pr "    free (ret.%s.%s_val);\n" n n;
5795            pr "    char *p = safe_malloc (g, 1);\n";
5796            pr "    *size_r = ret.%s.%s_len;\n" n n;
5797            pr "    return p;\n";
5798            pr "  }\n";
5799       );
5800
5801       pr "}\n\n"
5802   ) daemon_functions;
5803
5804   (* Functions to free structures. *)
5805   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5806   pr " * structure format is identical to the XDR format.  See note in\n";
5807   pr " * generator.ml.\n";
5808   pr " */\n";
5809   pr "\n";
5810
5811   List.iter (
5812     fun (typ, _) ->
5813       pr "void\n";
5814       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5815       pr "{\n";
5816       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5817       pr "  free (x);\n";
5818       pr "}\n";
5819       pr "\n";
5820
5821       pr "void\n";
5822       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5823       pr "{\n";
5824       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5825       pr "  free (x);\n";
5826       pr "}\n";
5827       pr "\n";
5828
5829   ) structs;
5830
5831 (* Generate daemon/actions.h. *)
5832 and generate_daemon_actions_h () =
5833   generate_header CStyle GPLv2plus;
5834
5835   pr "#include \"../src/guestfs_protocol.h\"\n";
5836   pr "\n";
5837
5838   List.iter (
5839     fun (name, style, _, _, _, _, _) ->
5840       generate_prototype
5841         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5842         name style;
5843   ) daemon_functions
5844
5845 (* Generate the linker script which controls the visibility of
5846  * symbols in the public ABI and ensures no other symbols get
5847  * exported accidentally.
5848  *)
5849 and generate_linker_script () =
5850   generate_header HashStyle GPLv2plus;
5851
5852   let globals = [
5853     "guestfs_create";
5854     "guestfs_close";
5855     "guestfs_get_error_handler";
5856     "guestfs_get_out_of_memory_handler";
5857     "guestfs_last_error";
5858     "guestfs_set_error_handler";
5859     "guestfs_set_launch_done_callback";
5860     "guestfs_set_log_message_callback";
5861     "guestfs_set_out_of_memory_handler";
5862     "guestfs_set_subprocess_quit_callback";
5863
5864     (* Unofficial parts of the API: the bindings code use these
5865      * functions, so it is useful to export them.
5866      *)
5867     "guestfs_safe_calloc";
5868     "guestfs_safe_malloc";
5869   ] in
5870   let functions =
5871     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5872       all_functions in
5873   let structs =
5874     List.concat (
5875       List.map (fun (typ, _) ->
5876                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5877         structs
5878     ) in
5879   let globals = List.sort compare (globals @ functions @ structs) in
5880
5881   pr "{\n";
5882   pr "    global:\n";
5883   List.iter (pr "        %s;\n") globals;
5884   pr "\n";
5885
5886   pr "    local:\n";
5887   pr "        *;\n";
5888   pr "};\n"
5889
5890 (* Generate the server-side stubs. *)
5891 and generate_daemon_actions () =
5892   generate_header CStyle GPLv2plus;
5893
5894   pr "#include <config.h>\n";
5895   pr "\n";
5896   pr "#include <stdio.h>\n";
5897   pr "#include <stdlib.h>\n";
5898   pr "#include <string.h>\n";
5899   pr "#include <inttypes.h>\n";
5900   pr "#include <rpc/types.h>\n";
5901   pr "#include <rpc/xdr.h>\n";
5902   pr "\n";
5903   pr "#include \"daemon.h\"\n";
5904   pr "#include \"c-ctype.h\"\n";
5905   pr "#include \"../src/guestfs_protocol.h\"\n";
5906   pr "#include \"actions.h\"\n";
5907   pr "\n";
5908
5909   List.iter (
5910     fun (name, style, _, _, _, _, _) ->
5911       (* Generate server-side stubs. *)
5912       pr "static void %s_stub (XDR *xdr_in)\n" name;
5913       pr "{\n";
5914       let error_code =
5915         match fst style with
5916         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5917         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5918         | RBool _ -> pr "  int r;\n"; "-1"
5919         | RConstString _ | RConstOptString _ ->
5920             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5921         | RString _ -> pr "  char *r;\n"; "NULL"
5922         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5923         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5924         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5925         | RBufferOut _ ->
5926             pr "  size_t size = 1;\n";
5927             pr "  char *r;\n";
5928             "NULL" in
5929
5930       (match snd style with
5931        | [] -> ()
5932        | args ->
5933            pr "  struct guestfs_%s_args args;\n" name;
5934            List.iter (
5935              function
5936              | Device n | Dev_or_Path n
5937              | Pathname n
5938              | String n -> ()
5939              | OptString n -> pr "  char *%s;\n" n
5940              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5941              | Bool n -> pr "  int %s;\n" n
5942              | Int n -> pr "  int %s;\n" n
5943              | Int64 n -> pr "  int64_t %s;\n" n
5944              | FileIn _ | FileOut _ -> ()
5945            ) args
5946       );
5947       pr "\n";
5948
5949       (match snd style with
5950        | [] -> ()
5951        | args ->
5952            pr "  memset (&args, 0, sizeof args);\n";
5953            pr "\n";
5954            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5955            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5956            pr "    return;\n";
5957            pr "  }\n";
5958            let pr_args n =
5959              pr "  char *%s = args.%s;\n" n n
5960            in
5961            let pr_list_handling_code n =
5962              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5963              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5964              pr "  if (%s == NULL) {\n" n;
5965              pr "    reply_with_perror (\"realloc\");\n";
5966              pr "    goto done;\n";
5967              pr "  }\n";
5968              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5969              pr "  args.%s.%s_val = %s;\n" n n n;
5970            in
5971            List.iter (
5972              function
5973              | Pathname n ->
5974                  pr_args n;
5975                  pr "  ABS_PATH (%s, goto done);\n" n;
5976              | Device n ->
5977                  pr_args n;
5978                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5979              | Dev_or_Path n ->
5980                  pr_args n;
5981                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5982              | String n -> pr_args n
5983              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5984              | StringList n ->
5985                  pr_list_handling_code n;
5986              | DeviceList n ->
5987                  pr_list_handling_code n;
5988                  pr "  /* Ensure that each is a device,\n";
5989                  pr "   * and perform device name translation. */\n";
5990                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5991                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5992                  pr "  }\n";
5993              | Bool n -> pr "  %s = args.%s;\n" n n
5994              | Int n -> pr "  %s = args.%s;\n" n n
5995              | Int64 n -> pr "  %s = args.%s;\n" n n
5996              | FileIn _ | FileOut _ -> ()
5997            ) args;
5998            pr "\n"
5999       );
6000
6001
6002       (* this is used at least for do_equal *)
6003       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6004         (* Emit NEED_ROOT just once, even when there are two or
6005            more Pathname args *)
6006         pr "  NEED_ROOT (goto done);\n";
6007       );
6008
6009       (* Don't want to call the impl with any FileIn or FileOut
6010        * parameters, since these go "outside" the RPC protocol.
6011        *)
6012       let args' =
6013         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6014           (snd style) in
6015       pr "  r = do_%s " name;
6016       generate_c_call_args (fst style, args');
6017       pr ";\n";
6018
6019       (match fst style with
6020        | RErr | RInt _ | RInt64 _ | RBool _
6021        | RConstString _ | RConstOptString _
6022        | RString _ | RStringList _ | RHashtable _
6023        | RStruct (_, _) | RStructList (_, _) ->
6024            pr "  if (r == %s)\n" error_code;
6025            pr "    /* do_%s has already called reply_with_error */\n" name;
6026            pr "    goto done;\n";
6027            pr "\n"
6028        | RBufferOut _ ->
6029            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6030            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6031            pr "   */\n";
6032            pr "  if (size == 1 && r == %s)\n" error_code;
6033            pr "    /* do_%s has already called reply_with_error */\n" name;
6034            pr "    goto done;\n";
6035            pr "\n"
6036       );
6037
6038       (* If there are any FileOut parameters, then the impl must
6039        * send its own reply.
6040        *)
6041       let no_reply =
6042         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6043       if no_reply then
6044         pr "  /* do_%s has already sent a reply */\n" name
6045       else (
6046         match fst style with
6047         | RErr -> pr "  reply (NULL, NULL);\n"
6048         | RInt n | RInt64 n | RBool n ->
6049             pr "  struct guestfs_%s_ret ret;\n" name;
6050             pr "  ret.%s = r;\n" n;
6051             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6052               name
6053         | RConstString _ | RConstOptString _ ->
6054             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6055         | RString n ->
6056             pr "  struct guestfs_%s_ret ret;\n" name;
6057             pr "  ret.%s = r;\n" n;
6058             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6059               name;
6060             pr "  free (r);\n"
6061         | RStringList n | RHashtable n ->
6062             pr "  struct guestfs_%s_ret ret;\n" name;
6063             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6064             pr "  ret.%s.%s_val = r;\n" n n;
6065             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6066               name;
6067             pr "  free_strings (r);\n"
6068         | RStruct (n, _) ->
6069             pr "  struct guestfs_%s_ret ret;\n" name;
6070             pr "  ret.%s = *r;\n" n;
6071             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6072               name;
6073             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6074               name
6075         | RStructList (n, _) ->
6076             pr "  struct guestfs_%s_ret ret;\n" name;
6077             pr "  ret.%s = *r;\n" n;
6078             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6079               name;
6080             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6081               name
6082         | RBufferOut n ->
6083             pr "  struct guestfs_%s_ret ret;\n" name;
6084             pr "  ret.%s.%s_val = r;\n" n n;
6085             pr "  ret.%s.%s_len = size;\n" n n;
6086             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6087               name;
6088             pr "  free (r);\n"
6089       );
6090
6091       (* Free the args. *)
6092       (match snd style with
6093        | [] ->
6094            pr "done: ;\n";
6095        | _ ->
6096            pr "done:\n";
6097            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6098              name
6099       );
6100
6101       pr "}\n\n";
6102   ) daemon_functions;
6103
6104   (* Dispatch function. *)
6105   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6106   pr "{\n";
6107   pr "  switch (proc_nr) {\n";
6108
6109   List.iter (
6110     fun (name, style, _, _, _, _, _) ->
6111       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6112       pr "      %s_stub (xdr_in);\n" name;
6113       pr "      break;\n"
6114   ) daemon_functions;
6115
6116   pr "    default:\n";
6117   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";
6118   pr "  }\n";
6119   pr "}\n";
6120   pr "\n";
6121
6122   (* LVM columns and tokenization functions. *)
6123   (* XXX This generates crap code.  We should rethink how we
6124    * do this parsing.
6125    *)
6126   List.iter (
6127     function
6128     | typ, cols ->
6129         pr "static const char *lvm_%s_cols = \"%s\";\n"
6130           typ (String.concat "," (List.map fst cols));
6131         pr "\n";
6132
6133         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6134         pr "{\n";
6135         pr "  char *tok, *p, *next;\n";
6136         pr "  int i, j;\n";
6137         pr "\n";
6138         (*
6139           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6140           pr "\n";
6141         *)
6142         pr "  if (!str) {\n";
6143         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6144         pr "    return -1;\n";
6145         pr "  }\n";
6146         pr "  if (!*str || c_isspace (*str)) {\n";
6147         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6148         pr "    return -1;\n";
6149         pr "  }\n";
6150         pr "  tok = str;\n";
6151         List.iter (
6152           fun (name, coltype) ->
6153             pr "  if (!tok) {\n";
6154             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6155             pr "    return -1;\n";
6156             pr "  }\n";
6157             pr "  p = strchrnul (tok, ',');\n";
6158             pr "  if (*p) next = p+1; else next = NULL;\n";
6159             pr "  *p = '\\0';\n";
6160             (match coltype with
6161              | FString ->
6162                  pr "  r->%s = strdup (tok);\n" name;
6163                  pr "  if (r->%s == NULL) {\n" name;
6164                  pr "    perror (\"strdup\");\n";
6165                  pr "    return -1;\n";
6166                  pr "  }\n"
6167              | FUUID ->
6168                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6169                  pr "    if (tok[j] == '\\0') {\n";
6170                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6171                  pr "      return -1;\n";
6172                  pr "    } else if (tok[j] != '-')\n";
6173                  pr "      r->%s[i++] = tok[j];\n" name;
6174                  pr "  }\n";
6175              | FBytes ->
6176                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6177                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6178                  pr "    return -1;\n";
6179                  pr "  }\n";
6180              | FInt64 ->
6181                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6182                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6183                  pr "    return -1;\n";
6184                  pr "  }\n";
6185              | FOptPercent ->
6186                  pr "  if (tok[0] == '\\0')\n";
6187                  pr "    r->%s = -1;\n" name;
6188                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6189                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6190                  pr "    return -1;\n";
6191                  pr "  }\n";
6192              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6193                  assert false (* can never be an LVM column *)
6194             );
6195             pr "  tok = next;\n";
6196         ) cols;
6197
6198         pr "  if (tok != NULL) {\n";
6199         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6200         pr "    return -1;\n";
6201         pr "  }\n";
6202         pr "  return 0;\n";
6203         pr "}\n";
6204         pr "\n";
6205
6206         pr "guestfs_int_lvm_%s_list *\n" typ;
6207         pr "parse_command_line_%ss (void)\n" typ;
6208         pr "{\n";
6209         pr "  char *out, *err;\n";
6210         pr "  char *p, *pend;\n";
6211         pr "  int r, i;\n";
6212         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6213         pr "  void *newp;\n";
6214         pr "\n";
6215         pr "  ret = malloc (sizeof *ret);\n";
6216         pr "  if (!ret) {\n";
6217         pr "    reply_with_perror (\"malloc\");\n";
6218         pr "    return NULL;\n";
6219         pr "  }\n";
6220         pr "\n";
6221         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6222         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6223         pr "\n";
6224         pr "  r = command (&out, &err,\n";
6225         pr "           \"lvm\", \"%ss\",\n" typ;
6226         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6227         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6228         pr "  if (r == -1) {\n";
6229         pr "    reply_with_error (\"%%s\", err);\n";
6230         pr "    free (out);\n";
6231         pr "    free (err);\n";
6232         pr "    free (ret);\n";
6233         pr "    return NULL;\n";
6234         pr "  }\n";
6235         pr "\n";
6236         pr "  free (err);\n";
6237         pr "\n";
6238         pr "  /* Tokenize each line of the output. */\n";
6239         pr "  p = out;\n";
6240         pr "  i = 0;\n";
6241         pr "  while (p) {\n";
6242         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6243         pr "    if (pend) {\n";
6244         pr "      *pend = '\\0';\n";
6245         pr "      pend++;\n";
6246         pr "    }\n";
6247         pr "\n";
6248         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6249         pr "      p++;\n";
6250         pr "\n";
6251         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6252         pr "      p = pend;\n";
6253         pr "      continue;\n";
6254         pr "    }\n";
6255         pr "\n";
6256         pr "    /* Allocate some space to store this next entry. */\n";
6257         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6258         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6259         pr "    if (newp == NULL) {\n";
6260         pr "      reply_with_perror (\"realloc\");\n";
6261         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6262         pr "      free (ret);\n";
6263         pr "      free (out);\n";
6264         pr "      return NULL;\n";
6265         pr "    }\n";
6266         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6267         pr "\n";
6268         pr "    /* Tokenize the next entry. */\n";
6269         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6270         pr "    if (r == -1) {\n";
6271         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6272         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6273         pr "      free (ret);\n";
6274         pr "      free (out);\n";
6275         pr "      return NULL;\n";
6276         pr "    }\n";
6277         pr "\n";
6278         pr "    ++i;\n";
6279         pr "    p = pend;\n";
6280         pr "  }\n";
6281         pr "\n";
6282         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6283         pr "\n";
6284         pr "  free (out);\n";
6285         pr "  return ret;\n";
6286         pr "}\n"
6287
6288   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6289
6290 (* Generate a list of function names, for debugging in the daemon.. *)
6291 and generate_daemon_names () =
6292   generate_header CStyle GPLv2plus;
6293
6294   pr "#include <config.h>\n";
6295   pr "\n";
6296   pr "#include \"daemon.h\"\n";
6297   pr "\n";
6298
6299   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6300   pr "const char *function_names[] = {\n";
6301   List.iter (
6302     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6303   ) daemon_functions;
6304   pr "};\n";
6305
6306 (* Generate the optional groups for the daemon to implement
6307  * guestfs_available.
6308  *)
6309 and generate_daemon_optgroups_c () =
6310   generate_header CStyle GPLv2plus;
6311
6312   pr "#include <config.h>\n";
6313   pr "\n";
6314   pr "#include \"daemon.h\"\n";
6315   pr "#include \"optgroups.h\"\n";
6316   pr "\n";
6317
6318   pr "struct optgroup optgroups[] = {\n";
6319   List.iter (
6320     fun (group, _) ->
6321       pr "  { \"%s\", optgroup_%s_available },\n" group group
6322   ) optgroups;
6323   pr "  { NULL, NULL }\n";
6324   pr "};\n"
6325
6326 and generate_daemon_optgroups_h () =
6327   generate_header CStyle GPLv2plus;
6328
6329   List.iter (
6330     fun (group, _) ->
6331       pr "extern int optgroup_%s_available (void);\n" group
6332   ) optgroups
6333
6334 (* Generate the tests. *)
6335 and generate_tests () =
6336   generate_header CStyle GPLv2plus;
6337
6338   pr "\
6339 #include <stdio.h>
6340 #include <stdlib.h>
6341 #include <string.h>
6342 #include <unistd.h>
6343 #include <sys/types.h>
6344 #include <fcntl.h>
6345
6346 #include \"guestfs.h\"
6347 #include \"guestfs-internal.h\"
6348
6349 static guestfs_h *g;
6350 static int suppress_error = 0;
6351
6352 static void print_error (guestfs_h *g, void *data, const char *msg)
6353 {
6354   if (!suppress_error)
6355     fprintf (stderr, \"%%s\\n\", msg);
6356 }
6357
6358 /* FIXME: nearly identical code appears in fish.c */
6359 static void print_strings (char *const *argv)
6360 {
6361   int argc;
6362
6363   for (argc = 0; argv[argc] != NULL; ++argc)
6364     printf (\"\\t%%s\\n\", argv[argc]);
6365 }
6366
6367 /*
6368 static void print_table (char const *const *argv)
6369 {
6370   int i;
6371
6372   for (i = 0; argv[i] != NULL; i += 2)
6373     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6374 }
6375 */
6376
6377 ";
6378
6379   (* Generate a list of commands which are not tested anywhere. *)
6380   pr "static void no_test_warnings (void)\n";
6381   pr "{\n";
6382
6383   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6384   List.iter (
6385     fun (_, _, _, _, tests, _, _) ->
6386       let tests = filter_map (
6387         function
6388         | (_, (Always|If _|Unless _), test) -> Some test
6389         | (_, Disabled, _) -> None
6390       ) tests in
6391       let seq = List.concat (List.map seq_of_test tests) in
6392       let cmds_tested = List.map List.hd seq in
6393       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6394   ) all_functions;
6395
6396   List.iter (
6397     fun (name, _, _, _, _, _, _) ->
6398       if not (Hashtbl.mem hash name) then
6399         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6400   ) all_functions;
6401
6402   pr "}\n";
6403   pr "\n";
6404
6405   (* Generate the actual tests.  Note that we generate the tests
6406    * in reverse order, deliberately, so that (in general) the
6407    * newest tests run first.  This makes it quicker and easier to
6408    * debug them.
6409    *)
6410   let test_names =
6411     List.map (
6412       fun (name, _, _, flags, tests, _, _) ->
6413         mapi (generate_one_test name flags) tests
6414     ) (List.rev all_functions) in
6415   let test_names = List.concat test_names in
6416   let nr_tests = List.length test_names in
6417
6418   pr "\
6419 int main (int argc, char *argv[])
6420 {
6421   char c = 0;
6422   unsigned long int n_failed = 0;
6423   const char *filename;
6424   int fd;
6425   int nr_tests, test_num = 0;
6426
6427   setbuf (stdout, NULL);
6428
6429   no_test_warnings ();
6430
6431   g = guestfs_create ();
6432   if (g == NULL) {
6433     printf (\"guestfs_create FAILED\\n\");
6434     exit (EXIT_FAILURE);
6435   }
6436
6437   guestfs_set_error_handler (g, print_error, NULL);
6438
6439   guestfs_set_path (g, \"../appliance\");
6440
6441   filename = \"test1.img\";
6442   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6443   if (fd == -1) {
6444     perror (filename);
6445     exit (EXIT_FAILURE);
6446   }
6447   if (lseek (fd, %d, SEEK_SET) == -1) {
6448     perror (\"lseek\");
6449     close (fd);
6450     unlink (filename);
6451     exit (EXIT_FAILURE);
6452   }
6453   if (write (fd, &c, 1) == -1) {
6454     perror (\"write\");
6455     close (fd);
6456     unlink (filename);
6457     exit (EXIT_FAILURE);
6458   }
6459   if (close (fd) == -1) {
6460     perror (filename);
6461     unlink (filename);
6462     exit (EXIT_FAILURE);
6463   }
6464   if (guestfs_add_drive (g, filename) == -1) {
6465     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6466     exit (EXIT_FAILURE);
6467   }
6468
6469   filename = \"test2.img\";
6470   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6471   if (fd == -1) {
6472     perror (filename);
6473     exit (EXIT_FAILURE);
6474   }
6475   if (lseek (fd, %d, SEEK_SET) == -1) {
6476     perror (\"lseek\");
6477     close (fd);
6478     unlink (filename);
6479     exit (EXIT_FAILURE);
6480   }
6481   if (write (fd, &c, 1) == -1) {
6482     perror (\"write\");
6483     close (fd);
6484     unlink (filename);
6485     exit (EXIT_FAILURE);
6486   }
6487   if (close (fd) == -1) {
6488     perror (filename);
6489     unlink (filename);
6490     exit (EXIT_FAILURE);
6491   }
6492   if (guestfs_add_drive (g, filename) == -1) {
6493     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6494     exit (EXIT_FAILURE);
6495   }
6496
6497   filename = \"test3.img\";
6498   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6499   if (fd == -1) {
6500     perror (filename);
6501     exit (EXIT_FAILURE);
6502   }
6503   if (lseek (fd, %d, SEEK_SET) == -1) {
6504     perror (\"lseek\");
6505     close (fd);
6506     unlink (filename);
6507     exit (EXIT_FAILURE);
6508   }
6509   if (write (fd, &c, 1) == -1) {
6510     perror (\"write\");
6511     close (fd);
6512     unlink (filename);
6513     exit (EXIT_FAILURE);
6514   }
6515   if (close (fd) == -1) {
6516     perror (filename);
6517     unlink (filename);
6518     exit (EXIT_FAILURE);
6519   }
6520   if (guestfs_add_drive (g, filename) == -1) {
6521     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6522     exit (EXIT_FAILURE);
6523   }
6524
6525   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6526     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6527     exit (EXIT_FAILURE);
6528   }
6529
6530   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6531   alarm (600);
6532
6533   if (guestfs_launch (g) == -1) {
6534     printf (\"guestfs_launch FAILED\\n\");
6535     exit (EXIT_FAILURE);
6536   }
6537
6538   /* Cancel previous alarm. */
6539   alarm (0);
6540
6541   nr_tests = %d;
6542
6543 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6544
6545   iteri (
6546     fun i test_name ->
6547       pr "  test_num++;\n";
6548       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6549       pr "  if (%s () == -1) {\n" test_name;
6550       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6551       pr "    n_failed++;\n";
6552       pr "  }\n";
6553   ) test_names;
6554   pr "\n";
6555
6556   pr "  guestfs_close (g);\n";
6557   pr "  unlink (\"test1.img\");\n";
6558   pr "  unlink (\"test2.img\");\n";
6559   pr "  unlink (\"test3.img\");\n";
6560   pr "\n";
6561
6562   pr "  if (n_failed > 0) {\n";
6563   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6564   pr "    exit (EXIT_FAILURE);\n";
6565   pr "  }\n";
6566   pr "\n";
6567
6568   pr "  exit (EXIT_SUCCESS);\n";
6569   pr "}\n"
6570
6571 and generate_one_test name flags i (init, prereq, test) =
6572   let test_name = sprintf "test_%s_%d" name i in
6573
6574   pr "\
6575 static int %s_skip (void)
6576 {
6577   const char *str;
6578
6579   str = getenv (\"TEST_ONLY\");
6580   if (str)
6581     return strstr (str, \"%s\") == NULL;
6582   str = getenv (\"SKIP_%s\");
6583   if (str && STREQ (str, \"1\")) return 1;
6584   str = getenv (\"SKIP_TEST_%s\");
6585   if (str && STREQ (str, \"1\")) return 1;
6586   return 0;
6587 }
6588
6589 " test_name name (String.uppercase test_name) (String.uppercase name);
6590
6591   (match prereq with
6592    | Disabled | Always -> ()
6593    | If code | Unless code ->
6594        pr "static int %s_prereq (void)\n" test_name;
6595        pr "{\n";
6596        pr "  %s\n" code;
6597        pr "}\n";
6598        pr "\n";
6599   );
6600
6601   pr "\
6602 static int %s (void)
6603 {
6604   if (%s_skip ()) {
6605     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6606     return 0;
6607   }
6608
6609 " test_name test_name test_name;
6610
6611   (* Optional functions should only be tested if the relevant
6612    * support is available in the daemon.
6613    *)
6614   List.iter (
6615     function
6616     | Optional group ->
6617         pr "  {\n";
6618         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6619         pr "    int r;\n";
6620         pr "    suppress_error = 1;\n";
6621         pr "    r = guestfs_available (g, (char **) groups);\n";
6622         pr "    suppress_error = 0;\n";
6623         pr "    if (r == -1) {\n";
6624         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6625         pr "      return 0;\n";
6626         pr "    }\n";
6627         pr "  }\n";
6628     | _ -> ()
6629   ) flags;
6630
6631   (match prereq with
6632    | Disabled ->
6633        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6634    | If _ ->
6635        pr "  if (! %s_prereq ()) {\n" test_name;
6636        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6637        pr "    return 0;\n";
6638        pr "  }\n";
6639        pr "\n";
6640        generate_one_test_body name i test_name init test;
6641    | Unless _ ->
6642        pr "  if (%s_prereq ()) {\n" test_name;
6643        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6644        pr "    return 0;\n";
6645        pr "  }\n";
6646        pr "\n";
6647        generate_one_test_body name i test_name init test;
6648    | Always ->
6649        generate_one_test_body name i test_name init test
6650   );
6651
6652   pr "  return 0;\n";
6653   pr "}\n";
6654   pr "\n";
6655   test_name
6656
6657 and generate_one_test_body name i test_name init test =
6658   (match init with
6659    | InitNone (* XXX at some point, InitNone and InitEmpty became
6660                * folded together as the same thing.  Really we should
6661                * make InitNone do nothing at all, but the tests may
6662                * need to be checked to make sure this is OK.
6663                *)
6664    | InitEmpty ->
6665        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6666        List.iter (generate_test_command_call test_name)
6667          [["blockdev_setrw"; "/dev/sda"];
6668           ["umount_all"];
6669           ["lvm_remove_all"]]
6670    | InitPartition ->
6671        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6672        List.iter (generate_test_command_call test_name)
6673          [["blockdev_setrw"; "/dev/sda"];
6674           ["umount_all"];
6675           ["lvm_remove_all"];
6676           ["part_disk"; "/dev/sda"; "mbr"]]
6677    | InitBasicFS ->
6678        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6679        List.iter (generate_test_command_call test_name)
6680          [["blockdev_setrw"; "/dev/sda"];
6681           ["umount_all"];
6682           ["lvm_remove_all"];
6683           ["part_disk"; "/dev/sda"; "mbr"];
6684           ["mkfs"; "ext2"; "/dev/sda1"];
6685           ["mount_options"; ""; "/dev/sda1"; "/"]]
6686    | InitBasicFSonLVM ->
6687        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6688          test_name;
6689        List.iter (generate_test_command_call test_name)
6690          [["blockdev_setrw"; "/dev/sda"];
6691           ["umount_all"];
6692           ["lvm_remove_all"];
6693           ["part_disk"; "/dev/sda"; "mbr"];
6694           ["pvcreate"; "/dev/sda1"];
6695           ["vgcreate"; "VG"; "/dev/sda1"];
6696           ["lvcreate"; "LV"; "VG"; "8"];
6697           ["mkfs"; "ext2"; "/dev/VG/LV"];
6698           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6699    | InitISOFS ->
6700        pr "  /* InitISOFS for %s */\n" test_name;
6701        List.iter (generate_test_command_call test_name)
6702          [["blockdev_setrw"; "/dev/sda"];
6703           ["umount_all"];
6704           ["lvm_remove_all"];
6705           ["mount_ro"; "/dev/sdd"; "/"]]
6706   );
6707
6708   let get_seq_last = function
6709     | [] ->
6710         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6711           test_name
6712     | seq ->
6713         let seq = List.rev seq in
6714         List.rev (List.tl seq), List.hd seq
6715   in
6716
6717   match test with
6718   | TestRun seq ->
6719       pr "  /* TestRun for %s (%d) */\n" name i;
6720       List.iter (generate_test_command_call test_name) seq
6721   | TestOutput (seq, expected) ->
6722       pr "  /* TestOutput for %s (%d) */\n" name i;
6723       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6724       let seq, last = get_seq_last seq in
6725       let test () =
6726         pr "    if (STRNEQ (r, expected)) {\n";
6727         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6728         pr "      return -1;\n";
6729         pr "    }\n"
6730       in
6731       List.iter (generate_test_command_call test_name) seq;
6732       generate_test_command_call ~test test_name last
6733   | TestOutputList (seq, expected) ->
6734       pr "  /* TestOutputList for %s (%d) */\n" name i;
6735       let seq, last = get_seq_last seq in
6736       let test () =
6737         iteri (
6738           fun i str ->
6739             pr "    if (!r[%d]) {\n" i;
6740             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6741             pr "      print_strings (r);\n";
6742             pr "      return -1;\n";
6743             pr "    }\n";
6744             pr "    {\n";
6745             pr "      const char *expected = \"%s\";\n" (c_quote str);
6746             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6747             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6748             pr "        return -1;\n";
6749             pr "      }\n";
6750             pr "    }\n"
6751         ) expected;
6752         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6753         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6754           test_name;
6755         pr "      print_strings (r);\n";
6756         pr "      return -1;\n";
6757         pr "    }\n"
6758       in
6759       List.iter (generate_test_command_call test_name) seq;
6760       generate_test_command_call ~test test_name last
6761   | TestOutputListOfDevices (seq, expected) ->
6762       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6763       let seq, last = get_seq_last seq in
6764       let test () =
6765         iteri (
6766           fun i str ->
6767             pr "    if (!r[%d]) {\n" i;
6768             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6769             pr "      print_strings (r);\n";
6770             pr "      return -1;\n";
6771             pr "    }\n";
6772             pr "    {\n";
6773             pr "      const char *expected = \"%s\";\n" (c_quote str);
6774             pr "      r[%d][5] = 's';\n" i;
6775             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6776             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6777             pr "        return -1;\n";
6778             pr "      }\n";
6779             pr "    }\n"
6780         ) expected;
6781         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6782         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6783           test_name;
6784         pr "      print_strings (r);\n";
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   | TestOutputInt (seq, expected) ->
6791       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6792       let seq, last = get_seq_last seq in
6793       let test () =
6794         pr "    if (r != %d) {\n" expected;
6795         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6796           test_name expected;
6797         pr "               (int) r);\n";
6798         pr "      return -1;\n";
6799         pr "    }\n"
6800       in
6801       List.iter (generate_test_command_call test_name) seq;
6802       generate_test_command_call ~test test_name last
6803   | TestOutputIntOp (seq, op, expected) ->
6804       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6805       let seq, last = get_seq_last seq in
6806       let test () =
6807         pr "    if (! (r %s %d)) {\n" op expected;
6808         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6809           test_name op expected;
6810         pr "               (int) r);\n";
6811         pr "      return -1;\n";
6812         pr "    }\n"
6813       in
6814       List.iter (generate_test_command_call test_name) seq;
6815       generate_test_command_call ~test test_name last
6816   | TestOutputTrue seq ->
6817       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6818       let seq, last = get_seq_last seq in
6819       let test () =
6820         pr "    if (!r) {\n";
6821         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6822           test_name;
6823         pr "      return -1;\n";
6824         pr "    }\n"
6825       in
6826       List.iter (generate_test_command_call test_name) seq;
6827       generate_test_command_call ~test test_name last
6828   | TestOutputFalse seq ->
6829       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6830       let seq, last = get_seq_last seq in
6831       let test () =
6832         pr "    if (r) {\n";
6833         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6834           test_name;
6835         pr "      return -1;\n";
6836         pr "    }\n"
6837       in
6838       List.iter (generate_test_command_call test_name) seq;
6839       generate_test_command_call ~test test_name last
6840   | TestOutputLength (seq, expected) ->
6841       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6842       let seq, last = get_seq_last seq in
6843       let test () =
6844         pr "    int j;\n";
6845         pr "    for (j = 0; j < %d; ++j)\n" expected;
6846         pr "      if (r[j] == NULL) {\n";
6847         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6848           test_name;
6849         pr "        print_strings (r);\n";
6850         pr "        return -1;\n";
6851         pr "      }\n";
6852         pr "    if (r[j] != NULL) {\n";
6853         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6854           test_name;
6855         pr "      print_strings (r);\n";
6856         pr "      return -1;\n";
6857         pr "    }\n"
6858       in
6859       List.iter (generate_test_command_call test_name) seq;
6860       generate_test_command_call ~test test_name last
6861   | TestOutputBuffer (seq, expected) ->
6862       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6863       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6864       let seq, last = get_seq_last seq in
6865       let len = String.length expected in
6866       let test () =
6867         pr "    if (size != %d) {\n" len;
6868         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6869         pr "      return -1;\n";
6870         pr "    }\n";
6871         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6872         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6873         pr "      return -1;\n";
6874         pr "    }\n"
6875       in
6876       List.iter (generate_test_command_call test_name) seq;
6877       generate_test_command_call ~test test_name last
6878   | TestOutputStruct (seq, checks) ->
6879       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6880       let seq, last = get_seq_last seq in
6881       let test () =
6882         List.iter (
6883           function
6884           | CompareWithInt (field, expected) ->
6885               pr "    if (r->%s != %d) {\n" field expected;
6886               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6887                 test_name field expected;
6888               pr "               (int) r->%s);\n" field;
6889               pr "      return -1;\n";
6890               pr "    }\n"
6891           | CompareWithIntOp (field, op, expected) ->
6892               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6893               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6894                 test_name field op expected;
6895               pr "               (int) r->%s);\n" field;
6896               pr "      return -1;\n";
6897               pr "    }\n"
6898           | CompareWithString (field, expected) ->
6899               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6900               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6901                 test_name field expected;
6902               pr "               r->%s);\n" field;
6903               pr "      return -1;\n";
6904               pr "    }\n"
6905           | CompareFieldsIntEq (field1, field2) ->
6906               pr "    if (r->%s != r->%s) {\n" field1 field2;
6907               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6908                 test_name field1 field2;
6909               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6910               pr "      return -1;\n";
6911               pr "    }\n"
6912           | CompareFieldsStrEq (field1, field2) ->
6913               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6914               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6915                 test_name field1 field2;
6916               pr "               r->%s, r->%s);\n" field1 field2;
6917               pr "      return -1;\n";
6918               pr "    }\n"
6919         ) checks
6920       in
6921       List.iter (generate_test_command_call test_name) seq;
6922       generate_test_command_call ~test test_name last
6923   | TestLastFail seq ->
6924       pr "  /* TestLastFail for %s (%d) */\n" name i;
6925       let seq, last = get_seq_last seq in
6926       List.iter (generate_test_command_call test_name) seq;
6927       generate_test_command_call test_name ~expect_error:true last
6928
6929 (* Generate the code to run a command, leaving the result in 'r'.
6930  * If you expect to get an error then you should set expect_error:true.
6931  *)
6932 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6933   match cmd with
6934   | [] -> assert false
6935   | name :: args ->
6936       (* Look up the command to find out what args/ret it has. *)
6937       let style =
6938         try
6939           let _, style, _, _, _, _, _ =
6940             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6941           style
6942         with Not_found ->
6943           failwithf "%s: in test, command %s was not found" test_name name in
6944
6945       if List.length (snd style) <> List.length args then
6946         failwithf "%s: in test, wrong number of args given to %s"
6947           test_name name;
6948
6949       pr "  {\n";
6950
6951       List.iter (
6952         function
6953         | OptString n, "NULL" -> ()
6954         | Pathname n, arg
6955         | Device n, arg
6956         | Dev_or_Path n, arg
6957         | String n, arg
6958         | OptString n, arg ->
6959             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6960         | Int _, _
6961         | Int64 _, _
6962         | Bool _, _
6963         | FileIn _, _ | FileOut _, _ -> ()
6964         | StringList n, "" | DeviceList n, "" ->
6965             pr "    const char *const %s[1] = { NULL };\n" n
6966         | StringList n, arg | DeviceList n, arg ->
6967             let strs = string_split " " arg in
6968             iteri (
6969               fun i str ->
6970                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6971             ) strs;
6972             pr "    const char *const %s[] = {\n" n;
6973             iteri (
6974               fun i _ -> pr "      %s_%d,\n" n i
6975             ) strs;
6976             pr "      NULL\n";
6977             pr "    };\n";
6978       ) (List.combine (snd style) args);
6979
6980       let error_code =
6981         match fst style with
6982         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6983         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6984         | RConstString _ | RConstOptString _ ->
6985             pr "    const char *r;\n"; "NULL"
6986         | RString _ -> pr "    char *r;\n"; "NULL"
6987         | RStringList _ | RHashtable _ ->
6988             pr "    char **r;\n";
6989             pr "    int i;\n";
6990             "NULL"
6991         | RStruct (_, typ) ->
6992             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6993         | RStructList (_, typ) ->
6994             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6995         | RBufferOut _ ->
6996             pr "    char *r;\n";
6997             pr "    size_t size;\n";
6998             "NULL" in
6999
7000       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7001       pr "    r = guestfs_%s (g" name;
7002
7003       (* Generate the parameters. *)
7004       List.iter (
7005         function
7006         | OptString _, "NULL" -> pr ", NULL"
7007         | Pathname n, _
7008         | Device n, _ | Dev_or_Path n, _
7009         | String n, _
7010         | OptString n, _ ->
7011             pr ", %s" n
7012         | FileIn _, arg | FileOut _, arg ->
7013             pr ", \"%s\"" (c_quote arg)
7014         | StringList n, _ | DeviceList n, _ ->
7015             pr ", (char **) %s" n
7016         | Int _, arg ->
7017             let i =
7018               try int_of_string arg
7019               with Failure "int_of_string" ->
7020                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7021             pr ", %d" i
7022         | Int64 _, arg ->
7023             let i =
7024               try Int64.of_string arg
7025               with Failure "int_of_string" ->
7026                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7027             pr ", %Ld" i
7028         | Bool _, arg ->
7029             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7030       ) (List.combine (snd style) args);
7031
7032       (match fst style with
7033        | RBufferOut _ -> pr ", &size"
7034        | _ -> ()
7035       );
7036
7037       pr ");\n";
7038
7039       if not expect_error then
7040         pr "    if (r == %s)\n" error_code
7041       else
7042         pr "    if (r != %s)\n" error_code;
7043       pr "      return -1;\n";
7044
7045       (* Insert the test code. *)
7046       (match test with
7047        | None -> ()
7048        | Some f -> f ()
7049       );
7050
7051       (match fst style with
7052        | RErr | RInt _ | RInt64 _ | RBool _
7053        | RConstString _ | RConstOptString _ -> ()
7054        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7055        | RStringList _ | RHashtable _ ->
7056            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7057            pr "      free (r[i]);\n";
7058            pr "    free (r);\n"
7059        | RStruct (_, typ) ->
7060            pr "    guestfs_free_%s (r);\n" typ
7061        | RStructList (_, typ) ->
7062            pr "    guestfs_free_%s_list (r);\n" typ
7063       );
7064
7065       pr "  }\n"
7066
7067 and c_quote str =
7068   let str = replace_str str "\r" "\\r" in
7069   let str = replace_str str "\n" "\\n" in
7070   let str = replace_str str "\t" "\\t" in
7071   let str = replace_str str "\000" "\\0" in
7072   str
7073
7074 (* Generate a lot of different functions for guestfish. *)
7075 and generate_fish_cmds () =
7076   generate_header CStyle GPLv2plus;
7077
7078   let all_functions =
7079     List.filter (
7080       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7081     ) all_functions in
7082   let all_functions_sorted =
7083     List.filter (
7084       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7085     ) all_functions_sorted in
7086
7087   pr "#include <config.h>\n";
7088   pr "\n";
7089   pr "#include <stdio.h>\n";
7090   pr "#include <stdlib.h>\n";
7091   pr "#include <string.h>\n";
7092   pr "#include <inttypes.h>\n";
7093   pr "\n";
7094   pr "#include <guestfs.h>\n";
7095   pr "#include \"c-ctype.h\"\n";
7096   pr "#include \"full-write.h\"\n";
7097   pr "#include \"xstrtol.h\"\n";
7098   pr "#include \"fish.h\"\n";
7099   pr "\n";
7100
7101   (* list_commands function, which implements guestfish -h *)
7102   pr "void list_commands (void)\n";
7103   pr "{\n";
7104   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7105   pr "  list_builtin_commands ();\n";
7106   List.iter (
7107     fun (name, _, _, flags, _, shortdesc, _) ->
7108       let name = replace_char name '_' '-' in
7109       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7110         name shortdesc
7111   ) all_functions_sorted;
7112   pr "  printf (\"    %%s\\n\",";
7113   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7114   pr "}\n";
7115   pr "\n";
7116
7117   (* display_command function, which implements guestfish -h cmd *)
7118   pr "void display_command (const char *cmd)\n";
7119   pr "{\n";
7120   List.iter (
7121     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7122       let name2 = replace_char name '_' '-' in
7123       let alias =
7124         try find_map (function FishAlias n -> Some n | _ -> None) flags
7125         with Not_found -> name in
7126       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7127       let synopsis =
7128         match snd style with
7129         | [] -> name2
7130         | args ->
7131             sprintf "%s %s"
7132               name2 (String.concat " " (List.map name_of_argt args)) in
7133
7134       let warnings =
7135         if List.mem ProtocolLimitWarning flags then
7136           ("\n\n" ^ protocol_limit_warning)
7137         else "" in
7138
7139       (* For DangerWillRobinson commands, we should probably have
7140        * guestfish prompt before allowing you to use them (especially
7141        * in interactive mode). XXX
7142        *)
7143       let warnings =
7144         warnings ^
7145           if List.mem DangerWillRobinson flags then
7146             ("\n\n" ^ danger_will_robinson)
7147           else "" in
7148
7149       let warnings =
7150         warnings ^
7151           match deprecation_notice flags with
7152           | None -> ""
7153           | Some txt -> "\n\n" ^ txt in
7154
7155       let describe_alias =
7156         if name <> alias then
7157           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7158         else "" in
7159
7160       pr "  if (";
7161       pr "STRCASEEQ (cmd, \"%s\")" name;
7162       if name <> name2 then
7163         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7164       if name <> alias then
7165         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7166       pr ")\n";
7167       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7168         name2 shortdesc
7169         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7170          "=head1 DESCRIPTION\n\n" ^
7171          longdesc ^ warnings ^ describe_alias);
7172       pr "  else\n"
7173   ) all_functions;
7174   pr "    display_builtin_command (cmd);\n";
7175   pr "}\n";
7176   pr "\n";
7177
7178   let emit_print_list_function typ =
7179     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7180       typ typ typ;
7181     pr "{\n";
7182     pr "  unsigned int i;\n";
7183     pr "\n";
7184     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7185     pr "    printf (\"[%%d] = {\\n\", i);\n";
7186     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7187     pr "    printf (\"}\\n\");\n";
7188     pr "  }\n";
7189     pr "}\n";
7190     pr "\n";
7191   in
7192
7193   (* print_* functions *)
7194   List.iter (
7195     fun (typ, cols) ->
7196       let needs_i =
7197         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7198
7199       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7200       pr "{\n";
7201       if needs_i then (
7202         pr "  unsigned int i;\n";
7203         pr "\n"
7204       );
7205       List.iter (
7206         function
7207         | name, FString ->
7208             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7209         | name, FUUID ->
7210             pr "  printf (\"%%s%s: \", indent);\n" name;
7211             pr "  for (i = 0; i < 32; ++i)\n";
7212             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7213             pr "  printf (\"\\n\");\n"
7214         | name, FBuffer ->
7215             pr "  printf (\"%%s%s: \", indent);\n" name;
7216             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7217             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7218             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7219             pr "    else\n";
7220             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7221             pr "  printf (\"\\n\");\n"
7222         | name, (FUInt64|FBytes) ->
7223             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7224               name typ name
7225         | name, FInt64 ->
7226             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7227               name typ name
7228         | name, FUInt32 ->
7229             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7230               name typ name
7231         | name, FInt32 ->
7232             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7233               name typ name
7234         | name, FChar ->
7235             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7236               name typ name
7237         | name, FOptPercent ->
7238             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7239               typ name name typ name;
7240             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7241       ) cols;
7242       pr "}\n";
7243       pr "\n";
7244   ) structs;
7245
7246   (* Emit a print_TYPE_list function definition only if that function is used. *)
7247   List.iter (
7248     function
7249     | typ, (RStructListOnly | RStructAndList) ->
7250         (* generate the function for typ *)
7251         emit_print_list_function typ
7252     | typ, _ -> () (* empty *)
7253   ) (rstructs_used_by all_functions);
7254
7255   (* Emit a print_TYPE function definition only if that function is used. *)
7256   List.iter (
7257     function
7258     | typ, (RStructOnly | RStructAndList) ->
7259         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7260         pr "{\n";
7261         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7262         pr "}\n";
7263         pr "\n";
7264     | typ, _ -> () (* empty *)
7265   ) (rstructs_used_by all_functions);
7266
7267   (* run_<action> actions *)
7268   List.iter (
7269     fun (name, style, _, flags, _, _, _) ->
7270       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7271       pr "{\n";
7272       (match fst style with
7273        | RErr
7274        | RInt _
7275        | RBool _ -> pr "  int r;\n"
7276        | RInt64 _ -> pr "  int64_t r;\n"
7277        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7278        | RString _ -> pr "  char *r;\n"
7279        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7280        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7281        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7282        | RBufferOut _ ->
7283            pr "  char *r;\n";
7284            pr "  size_t size;\n";
7285       );
7286       List.iter (
7287         function
7288         | Device n
7289         | String n
7290         | OptString n
7291         | FileIn n
7292         | FileOut n -> pr "  const char *%s;\n" n
7293         | Pathname n
7294         | Dev_or_Path n -> pr "  char *%s;\n" n
7295         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7296         | Bool n -> pr "  int %s;\n" n
7297         | Int n -> pr "  int %s;\n" n
7298         | Int64 n -> pr "  int64_t %s;\n" n
7299       ) (snd style);
7300
7301       (* Check and convert parameters. *)
7302       let argc_expected = List.length (snd style) in
7303       pr "  if (argc != %d) {\n" argc_expected;
7304       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7305         argc_expected;
7306       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7307       pr "    return -1;\n";
7308       pr "  }\n";
7309
7310       let parse_integer fn fntyp rtyp range name i =
7311         pr "  {\n";
7312         pr "    strtol_error xerr;\n";
7313         pr "    %s r;\n" fntyp;
7314         pr "\n";
7315         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7316         pr "    if (xerr != LONGINT_OK) {\n";
7317         pr "      fprintf (stderr,\n";
7318         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7319         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7320         pr "      return -1;\n";
7321         pr "    }\n";
7322         (match range with
7323          | None -> ()
7324          | Some (min, max, comment) ->
7325              pr "    /* %s */\n" comment;
7326              pr "    if (r < %s || r > %s) {\n" min max;
7327              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7328                name;
7329              pr "      return -1;\n";
7330              pr "    }\n";
7331              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7332         );
7333         pr "    %s = r;\n" name;
7334         pr "  }\n";
7335       in
7336
7337       iteri (
7338         fun i ->
7339           function
7340           | Device name
7341           | String name ->
7342               pr "  %s = argv[%d];\n" name i
7343           | Pathname name
7344           | Dev_or_Path name ->
7345               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7346               pr "  if (%s == NULL) return -1;\n" name
7347           | OptString name ->
7348               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7349                 name i i
7350           | FileIn name ->
7351               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7352                 name i i
7353           | FileOut name ->
7354               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7355                 name i i
7356           | StringList name | DeviceList name ->
7357               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7358               pr "  if (%s == NULL) return -1;\n" name;
7359           | Bool name ->
7360               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7361           | Int name ->
7362               let range =
7363                 let min = "(-(2LL<<30))"
7364                 and max = "((2LL<<30)-1)"
7365                 and comment =
7366                   "The Int type in the generator is a signed 31 bit int." in
7367                 Some (min, max, comment) in
7368               parse_integer "xstrtoll" "long long" "int" range name i
7369           | Int64 name ->
7370               parse_integer "xstrtoll" "long long" "int64_t" None name i
7371       ) (snd style);
7372
7373       (* Call C API function. *)
7374       let fn =
7375         try find_map (function FishAction n -> Some n | _ -> None) flags
7376         with Not_found -> sprintf "guestfs_%s" name in
7377       pr "  r = %s " fn;
7378       generate_c_call_args ~handle:"g" style;
7379       pr ";\n";
7380
7381       List.iter (
7382         function
7383         | Device name | String name
7384         | OptString name | FileIn name | FileOut name | Bool name
7385         | Int name | Int64 name -> ()
7386         | Pathname name | Dev_or_Path name ->
7387             pr "  free (%s);\n" name
7388         | StringList name | DeviceList name ->
7389             pr "  free_strings (%s);\n" name
7390       ) (snd style);
7391
7392       (* Check return value for errors and display command results. *)
7393       (match fst style with
7394        | RErr -> pr "  return r;\n"
7395        | RInt _ ->
7396            pr "  if (r == -1) return -1;\n";
7397            pr "  printf (\"%%d\\n\", r);\n";
7398            pr "  return 0;\n"
7399        | RInt64 _ ->
7400            pr "  if (r == -1) return -1;\n";
7401            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7402            pr "  return 0;\n"
7403        | RBool _ ->
7404            pr "  if (r == -1) return -1;\n";
7405            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7406            pr "  return 0;\n"
7407        | RConstString _ ->
7408            pr "  if (r == NULL) return -1;\n";
7409            pr "  printf (\"%%s\\n\", r);\n";
7410            pr "  return 0;\n"
7411        | RConstOptString _ ->
7412            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7413            pr "  return 0;\n"
7414        | RString _ ->
7415            pr "  if (r == NULL) return -1;\n";
7416            pr "  printf (\"%%s\\n\", r);\n";
7417            pr "  free (r);\n";
7418            pr "  return 0;\n"
7419        | RStringList _ ->
7420            pr "  if (r == NULL) return -1;\n";
7421            pr "  print_strings (r);\n";
7422            pr "  free_strings (r);\n";
7423            pr "  return 0;\n"
7424        | RStruct (_, typ) ->
7425            pr "  if (r == NULL) return -1;\n";
7426            pr "  print_%s (r);\n" typ;
7427            pr "  guestfs_free_%s (r);\n" typ;
7428            pr "  return 0;\n"
7429        | RStructList (_, typ) ->
7430            pr "  if (r == NULL) return -1;\n";
7431            pr "  print_%s_list (r);\n" typ;
7432            pr "  guestfs_free_%s_list (r);\n" typ;
7433            pr "  return 0;\n"
7434        | RHashtable _ ->
7435            pr "  if (r == NULL) return -1;\n";
7436            pr "  print_table (r);\n";
7437            pr "  free_strings (r);\n";
7438            pr "  return 0;\n"
7439        | RBufferOut _ ->
7440            pr "  if (r == NULL) return -1;\n";
7441            pr "  if (full_write (1, r, size) != size) {\n";
7442            pr "    perror (\"write\");\n";
7443            pr "    free (r);\n";
7444            pr "    return -1;\n";
7445            pr "  }\n";
7446            pr "  free (r);\n";
7447            pr "  return 0;\n"
7448       );
7449       pr "}\n";
7450       pr "\n"
7451   ) all_functions;
7452
7453   (* run_action function *)
7454   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7455   pr "{\n";
7456   List.iter (
7457     fun (name, _, _, flags, _, _, _) ->
7458       let name2 = replace_char name '_' '-' in
7459       let alias =
7460         try find_map (function FishAlias n -> Some n | _ -> None) flags
7461         with Not_found -> name in
7462       pr "  if (";
7463       pr "STRCASEEQ (cmd, \"%s\")" name;
7464       if name <> name2 then
7465         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7466       if name <> alias then
7467         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7468       pr ")\n";
7469       pr "    return run_%s (cmd, argc, argv);\n" name;
7470       pr "  else\n";
7471   ) all_functions;
7472   pr "    {\n";
7473   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7474   pr "      if (command_num == 1)\n";
7475   pr "        extended_help_message ();\n";
7476   pr "      return -1;\n";
7477   pr "    }\n";
7478   pr "  return 0;\n";
7479   pr "}\n";
7480   pr "\n"
7481
7482 (* Readline completion for guestfish. *)
7483 and generate_fish_completion () =
7484   generate_header CStyle GPLv2plus;
7485
7486   let all_functions =
7487     List.filter (
7488       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7489     ) all_functions in
7490
7491   pr "\
7492 #include <config.h>
7493
7494 #include <stdio.h>
7495 #include <stdlib.h>
7496 #include <string.h>
7497
7498 #ifdef HAVE_LIBREADLINE
7499 #include <readline/readline.h>
7500 #endif
7501
7502 #include \"fish.h\"
7503
7504 #ifdef HAVE_LIBREADLINE
7505
7506 static const char *const commands[] = {
7507   BUILTIN_COMMANDS_FOR_COMPLETION,
7508 ";
7509
7510   (* Get the commands, including the aliases.  They don't need to be
7511    * sorted - the generator() function just does a dumb linear search.
7512    *)
7513   let commands =
7514     List.map (
7515       fun (name, _, _, flags, _, _, _) ->
7516         let name2 = replace_char name '_' '-' in
7517         let alias =
7518           try find_map (function FishAlias n -> Some n | _ -> None) flags
7519           with Not_found -> name in
7520
7521         if name <> alias then [name2; alias] else [name2]
7522     ) all_functions in
7523   let commands = List.flatten commands in
7524
7525   List.iter (pr "  \"%s\",\n") commands;
7526
7527   pr "  NULL
7528 };
7529
7530 static char *
7531 generator (const char *text, int state)
7532 {
7533   static int index, len;
7534   const char *name;
7535
7536   if (!state) {
7537     index = 0;
7538     len = strlen (text);
7539   }
7540
7541   rl_attempted_completion_over = 1;
7542
7543   while ((name = commands[index]) != NULL) {
7544     index++;
7545     if (STRCASEEQLEN (name, text, len))
7546       return strdup (name);
7547   }
7548
7549   return NULL;
7550 }
7551
7552 #endif /* HAVE_LIBREADLINE */
7553
7554 #ifdef HAVE_RL_COMPLETION_MATCHES
7555 #define RL_COMPLETION_MATCHES rl_completion_matches
7556 #else
7557 #ifdef HAVE_COMPLETION_MATCHES
7558 #define RL_COMPLETION_MATCHES completion_matches
7559 #endif
7560 #endif /* else just fail if we don't have either symbol */
7561
7562 char **
7563 do_completion (const char *text, int start, int end)
7564 {
7565   char **matches = NULL;
7566
7567 #ifdef HAVE_LIBREADLINE
7568   rl_completion_append_character = ' ';
7569
7570   if (start == 0)
7571     matches = RL_COMPLETION_MATCHES (text, generator);
7572   else if (complete_dest_paths)
7573     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7574 #endif
7575
7576   return matches;
7577 }
7578 ";
7579
7580 (* Generate the POD documentation for guestfish. *)
7581 and generate_fish_actions_pod () =
7582   let all_functions_sorted =
7583     List.filter (
7584       fun (_, _, _, flags, _, _, _) ->
7585         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7586     ) all_functions_sorted in
7587
7588   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7589
7590   List.iter (
7591     fun (name, style, _, flags, _, _, longdesc) ->
7592       let longdesc =
7593         Str.global_substitute rex (
7594           fun s ->
7595             let sub =
7596               try Str.matched_group 1 s
7597               with Not_found ->
7598                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7599             "C<" ^ replace_char sub '_' '-' ^ ">"
7600         ) longdesc in
7601       let name = replace_char name '_' '-' in
7602       let alias =
7603         try find_map (function FishAlias n -> Some n | _ -> None) flags
7604         with Not_found -> name in
7605
7606       pr "=head2 %s" name;
7607       if name <> alias then
7608         pr " | %s" alias;
7609       pr "\n";
7610       pr "\n";
7611       pr " %s" name;
7612       List.iter (
7613         function
7614         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7615         | OptString n -> pr " %s" n
7616         | StringList n | DeviceList n -> pr " '%s ...'" n
7617         | Bool _ -> pr " true|false"
7618         | Int n -> pr " %s" n
7619         | Int64 n -> pr " %s" n
7620         | FileIn n | FileOut n -> pr " (%s|-)" n
7621       ) (snd style);
7622       pr "\n";
7623       pr "\n";
7624       pr "%s\n\n" longdesc;
7625
7626       if List.exists (function FileIn _ | FileOut _ -> true
7627                       | _ -> false) (snd style) then
7628         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7629
7630       if List.mem ProtocolLimitWarning flags then
7631         pr "%s\n\n" protocol_limit_warning;
7632
7633       if List.mem DangerWillRobinson flags then
7634         pr "%s\n\n" danger_will_robinson;
7635
7636       match deprecation_notice flags with
7637       | None -> ()
7638       | Some txt -> pr "%s\n\n" txt
7639   ) all_functions_sorted
7640
7641 (* Generate a C function prototype. *)
7642 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7643     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7644     ?(prefix = "")
7645     ?handle name style =
7646   if extern then pr "extern ";
7647   if static then pr "static ";
7648   (match fst style with
7649    | RErr -> pr "int "
7650    | RInt _ -> pr "int "
7651    | RInt64 _ -> pr "int64_t "
7652    | RBool _ -> pr "int "
7653    | RConstString _ | RConstOptString _ -> pr "const char *"
7654    | RString _ | RBufferOut _ -> pr "char *"
7655    | RStringList _ | RHashtable _ -> pr "char **"
7656    | RStruct (_, typ) ->
7657        if not in_daemon then pr "struct guestfs_%s *" typ
7658        else pr "guestfs_int_%s *" typ
7659    | RStructList (_, typ) ->
7660        if not in_daemon then pr "struct guestfs_%s_list *" typ
7661        else pr "guestfs_int_%s_list *" typ
7662   );
7663   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7664   pr "%s%s (" prefix name;
7665   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7666     pr "void"
7667   else (
7668     let comma = ref false in
7669     (match handle with
7670      | None -> ()
7671      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7672     );
7673     let next () =
7674       if !comma then (
7675         if single_line then pr ", " else pr ",\n\t\t"
7676       );
7677       comma := true
7678     in
7679     List.iter (
7680       function
7681       | Pathname n
7682       | Device n | Dev_or_Path n
7683       | String n
7684       | OptString n ->
7685           next ();
7686           pr "const char *%s" n
7687       | StringList n | DeviceList n ->
7688           next ();
7689           pr "char *const *%s" n
7690       | Bool n -> next (); pr "int %s" n
7691       | Int n -> next (); pr "int %s" n
7692       | Int64 n -> next (); pr "int64_t %s" n
7693       | FileIn n
7694       | FileOut n ->
7695           if not in_daemon then (next (); pr "const char *%s" n)
7696     ) (snd style);
7697     if is_RBufferOut then (next (); pr "size_t *size_r");
7698   );
7699   pr ")";
7700   if semicolon then pr ";";
7701   if newline then pr "\n"
7702
7703 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7704 and generate_c_call_args ?handle ?(decl = false) style =
7705   pr "(";
7706   let comma = ref false in
7707   let next () =
7708     if !comma then pr ", ";
7709     comma := true
7710   in
7711   (match handle with
7712    | None -> ()
7713    | Some handle -> pr "%s" handle; comma := true
7714   );
7715   List.iter (
7716     fun arg ->
7717       next ();
7718       pr "%s" (name_of_argt arg)
7719   ) (snd style);
7720   (* For RBufferOut calls, add implicit &size parameter. *)
7721   if not decl then (
7722     match fst style with
7723     | RBufferOut _ ->
7724         next ();
7725         pr "&size"
7726     | _ -> ()
7727   );
7728   pr ")"
7729
7730 (* Generate the OCaml bindings interface. *)
7731 and generate_ocaml_mli () =
7732   generate_header OCamlStyle LGPLv2plus;
7733
7734   pr "\
7735 (** For API documentation you should refer to the C API
7736     in the guestfs(3) manual page.  The OCaml API uses almost
7737     exactly the same calls. *)
7738
7739 type t
7740 (** A [guestfs_h] handle. *)
7741
7742 exception Error of string
7743 (** This exception is raised when there is an error. *)
7744
7745 exception Handle_closed of string
7746 (** This exception is raised if you use a {!Guestfs.t} handle
7747     after calling {!close} on it.  The string is the name of
7748     the function. *)
7749
7750 val create : unit -> t
7751 (** Create a {!Guestfs.t} handle. *)
7752
7753 val close : t -> unit
7754 (** Close the {!Guestfs.t} handle and free up all resources used
7755     by it immediately.
7756
7757     Handles are closed by the garbage collector when they become
7758     unreferenced, but callers can call this in order to provide
7759     predictable cleanup. *)
7760
7761 ";
7762   generate_ocaml_structure_decls ();
7763
7764   (* The actions. *)
7765   List.iter (
7766     fun (name, style, _, _, _, shortdesc, _) ->
7767       generate_ocaml_prototype name style;
7768       pr "(** %s *)\n" shortdesc;
7769       pr "\n"
7770   ) all_functions_sorted
7771
7772 (* Generate the OCaml bindings implementation. *)
7773 and generate_ocaml_ml () =
7774   generate_header OCamlStyle LGPLv2plus;
7775
7776   pr "\
7777 type t
7778
7779 exception Error of string
7780 exception Handle_closed of string
7781
7782 external create : unit -> t = \"ocaml_guestfs_create\"
7783 external close : t -> unit = \"ocaml_guestfs_close\"
7784
7785 (* Give the exceptions names, so they can be raised from the C code. *)
7786 let () =
7787   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7788   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7789
7790 ";
7791
7792   generate_ocaml_structure_decls ();
7793
7794   (* The actions. *)
7795   List.iter (
7796     fun (name, style, _, _, _, shortdesc, _) ->
7797       generate_ocaml_prototype ~is_external:true name style;
7798   ) all_functions_sorted
7799
7800 (* Generate the OCaml bindings C implementation. *)
7801 and generate_ocaml_c () =
7802   generate_header CStyle LGPLv2plus;
7803
7804   pr "\
7805 #include <stdio.h>
7806 #include <stdlib.h>
7807 #include <string.h>
7808
7809 #include <caml/config.h>
7810 #include <caml/alloc.h>
7811 #include <caml/callback.h>
7812 #include <caml/fail.h>
7813 #include <caml/memory.h>
7814 #include <caml/mlvalues.h>
7815 #include <caml/signals.h>
7816
7817 #include <guestfs.h>
7818
7819 #include \"guestfs_c.h\"
7820
7821 /* Copy a hashtable of string pairs into an assoc-list.  We return
7822  * the list in reverse order, but hashtables aren't supposed to be
7823  * ordered anyway.
7824  */
7825 static CAMLprim value
7826 copy_table (char * const * argv)
7827 {
7828   CAMLparam0 ();
7829   CAMLlocal5 (rv, pairv, kv, vv, cons);
7830   int i;
7831
7832   rv = Val_int (0);
7833   for (i = 0; argv[i] != NULL; i += 2) {
7834     kv = caml_copy_string (argv[i]);
7835     vv = caml_copy_string (argv[i+1]);
7836     pairv = caml_alloc (2, 0);
7837     Store_field (pairv, 0, kv);
7838     Store_field (pairv, 1, vv);
7839     cons = caml_alloc (2, 0);
7840     Store_field (cons, 1, rv);
7841     rv = cons;
7842     Store_field (cons, 0, pairv);
7843   }
7844
7845   CAMLreturn (rv);
7846 }
7847
7848 ";
7849
7850   (* Struct copy functions. *)
7851
7852   let emit_ocaml_copy_list_function typ =
7853     pr "static CAMLprim value\n";
7854     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7855     pr "{\n";
7856     pr "  CAMLparam0 ();\n";
7857     pr "  CAMLlocal2 (rv, v);\n";
7858     pr "  unsigned int i;\n";
7859     pr "\n";
7860     pr "  if (%ss->len == 0)\n" typ;
7861     pr "    CAMLreturn (Atom (0));\n";
7862     pr "  else {\n";
7863     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7864     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7865     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7866     pr "      caml_modify (&Field (rv, i), v);\n";
7867     pr "    }\n";
7868     pr "    CAMLreturn (rv);\n";
7869     pr "  }\n";
7870     pr "}\n";
7871     pr "\n";
7872   in
7873
7874   List.iter (
7875     fun (typ, cols) ->
7876       let has_optpercent_col =
7877         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7878
7879       pr "static CAMLprim value\n";
7880       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7881       pr "{\n";
7882       pr "  CAMLparam0 ();\n";
7883       if has_optpercent_col then
7884         pr "  CAMLlocal3 (rv, v, v2);\n"
7885       else
7886         pr "  CAMLlocal2 (rv, v);\n";
7887       pr "\n";
7888       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7889       iteri (
7890         fun i col ->
7891           (match col with
7892            | name, FString ->
7893                pr "  v = caml_copy_string (%s->%s);\n" typ name
7894            | name, FBuffer ->
7895                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7896                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7897                  typ name typ name
7898            | name, FUUID ->
7899                pr "  v = caml_alloc_string (32);\n";
7900                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7901            | name, (FBytes|FInt64|FUInt64) ->
7902                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7903            | name, (FInt32|FUInt32) ->
7904                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7905            | name, FOptPercent ->
7906                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7907                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7908                pr "    v = caml_alloc (1, 0);\n";
7909                pr "    Store_field (v, 0, v2);\n";
7910                pr "  } else /* None */\n";
7911                pr "    v = Val_int (0);\n";
7912            | name, FChar ->
7913                pr "  v = Val_int (%s->%s);\n" typ name
7914           );
7915           pr "  Store_field (rv, %d, v);\n" i
7916       ) cols;
7917       pr "  CAMLreturn (rv);\n";
7918       pr "}\n";
7919       pr "\n";
7920   ) structs;
7921
7922   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7923   List.iter (
7924     function
7925     | typ, (RStructListOnly | RStructAndList) ->
7926         (* generate the function for typ *)
7927         emit_ocaml_copy_list_function typ
7928     | typ, _ -> () (* empty *)
7929   ) (rstructs_used_by all_functions);
7930
7931   (* The wrappers. *)
7932   List.iter (
7933     fun (name, style, _, _, _, _, _) ->
7934       pr "/* Automatically generated wrapper for function\n";
7935       pr " * ";
7936       generate_ocaml_prototype name style;
7937       pr " */\n";
7938       pr "\n";
7939
7940       let params =
7941         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7942
7943       let needs_extra_vs =
7944         match fst style with RConstOptString _ -> true | _ -> false in
7945
7946       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7947       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7948       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7949       pr "\n";
7950
7951       pr "CAMLprim value\n";
7952       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7953       List.iter (pr ", value %s") (List.tl params);
7954       pr ")\n";
7955       pr "{\n";
7956
7957       (match params with
7958        | [p1; p2; p3; p4; p5] ->
7959            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7960        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7961            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7962            pr "  CAMLxparam%d (%s);\n"
7963              (List.length rest) (String.concat ", " rest)
7964        | ps ->
7965            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7966       );
7967       if not needs_extra_vs then
7968         pr "  CAMLlocal1 (rv);\n"
7969       else
7970         pr "  CAMLlocal3 (rv, v, v2);\n";
7971       pr "\n";
7972
7973       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7974       pr "  if (g == NULL)\n";
7975       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7976       pr "\n";
7977
7978       List.iter (
7979         function
7980         | Pathname n
7981         | Device n | Dev_or_Path n
7982         | String n
7983         | FileIn n
7984         | FileOut n ->
7985             pr "  const char *%s = String_val (%sv);\n" n n
7986         | OptString n ->
7987             pr "  const char *%s =\n" n;
7988             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7989               n n
7990         | StringList n | DeviceList n ->
7991             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7992         | Bool n ->
7993             pr "  int %s = Bool_val (%sv);\n" n n
7994         | Int n ->
7995             pr "  int %s = Int_val (%sv);\n" n n
7996         | Int64 n ->
7997             pr "  int64_t %s = Int64_val (%sv);\n" n n
7998       ) (snd style);
7999       let error_code =
8000         match fst style with
8001         | RErr -> pr "  int r;\n"; "-1"
8002         | RInt _ -> pr "  int r;\n"; "-1"
8003         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8004         | RBool _ -> pr "  int r;\n"; "-1"
8005         | RConstString _ | RConstOptString _ ->
8006             pr "  const char *r;\n"; "NULL"
8007         | RString _ -> pr "  char *r;\n"; "NULL"
8008         | RStringList _ ->
8009             pr "  int i;\n";
8010             pr "  char **r;\n";
8011             "NULL"
8012         | RStruct (_, typ) ->
8013             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8014         | RStructList (_, typ) ->
8015             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8016         | RHashtable _ ->
8017             pr "  int i;\n";
8018             pr "  char **r;\n";
8019             "NULL"
8020         | RBufferOut _ ->
8021             pr "  char *r;\n";
8022             pr "  size_t size;\n";
8023             "NULL" in
8024       pr "\n";
8025
8026       pr "  caml_enter_blocking_section ();\n";
8027       pr "  r = guestfs_%s " name;
8028       generate_c_call_args ~handle:"g" style;
8029       pr ";\n";
8030       pr "  caml_leave_blocking_section ();\n";
8031
8032       List.iter (
8033         function
8034         | StringList n | DeviceList n ->
8035             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8036         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8037         | Bool _ | Int _ | Int64 _
8038         | FileIn _ | FileOut _ -> ()
8039       ) (snd style);
8040
8041       pr "  if (r == %s)\n" error_code;
8042       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8043       pr "\n";
8044
8045       (match fst style with
8046        | RErr -> pr "  rv = Val_unit;\n"
8047        | RInt _ -> pr "  rv = Val_int (r);\n"
8048        | RInt64 _ ->
8049            pr "  rv = caml_copy_int64 (r);\n"
8050        | RBool _ -> pr "  rv = Val_bool (r);\n"
8051        | RConstString _ ->
8052            pr "  rv = caml_copy_string (r);\n"
8053        | RConstOptString _ ->
8054            pr "  if (r) { /* Some string */\n";
8055            pr "    v = caml_alloc (1, 0);\n";
8056            pr "    v2 = caml_copy_string (r);\n";
8057            pr "    Store_field (v, 0, v2);\n";
8058            pr "  } else /* None */\n";
8059            pr "    v = Val_int (0);\n";
8060        | RString _ ->
8061            pr "  rv = caml_copy_string (r);\n";
8062            pr "  free (r);\n"
8063        | RStringList _ ->
8064            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8065            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8066            pr "  free (r);\n"
8067        | RStruct (_, typ) ->
8068            pr "  rv = copy_%s (r);\n" typ;
8069            pr "  guestfs_free_%s (r);\n" typ;
8070        | RStructList (_, typ) ->
8071            pr "  rv = copy_%s_list (r);\n" typ;
8072            pr "  guestfs_free_%s_list (r);\n" typ;
8073        | RHashtable _ ->
8074            pr "  rv = copy_table (r);\n";
8075            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8076            pr "  free (r);\n";
8077        | RBufferOut _ ->
8078            pr "  rv = caml_alloc_string (size);\n";
8079            pr "  memcpy (String_val (rv), r, size);\n";
8080       );
8081
8082       pr "  CAMLreturn (rv);\n";
8083       pr "}\n";
8084       pr "\n";
8085
8086       if List.length params > 5 then (
8087         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8088         pr "CAMLprim value ";
8089         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8090         pr "CAMLprim value\n";
8091         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8092         pr "{\n";
8093         pr "  return ocaml_guestfs_%s (argv[0]" name;
8094         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8095         pr ");\n";
8096         pr "}\n";
8097         pr "\n"
8098       )
8099   ) all_functions_sorted
8100
8101 and generate_ocaml_structure_decls () =
8102   List.iter (
8103     fun (typ, cols) ->
8104       pr "type %s = {\n" typ;
8105       List.iter (
8106         function
8107         | name, FString -> pr "  %s : string;\n" name
8108         | name, FBuffer -> pr "  %s : string;\n" name
8109         | name, FUUID -> pr "  %s : string;\n" name
8110         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8111         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8112         | name, FChar -> pr "  %s : char;\n" name
8113         | name, FOptPercent -> pr "  %s : float option;\n" name
8114       ) cols;
8115       pr "}\n";
8116       pr "\n"
8117   ) structs
8118
8119 and generate_ocaml_prototype ?(is_external = false) name style =
8120   if is_external then pr "external " else pr "val ";
8121   pr "%s : t -> " name;
8122   List.iter (
8123     function
8124     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8125     | OptString _ -> pr "string option -> "
8126     | StringList _ | DeviceList _ -> pr "string array -> "
8127     | Bool _ -> pr "bool -> "
8128     | Int _ -> pr "int -> "
8129     | Int64 _ -> pr "int64 -> "
8130   ) (snd style);
8131   (match fst style with
8132    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8133    | RInt _ -> pr "int"
8134    | RInt64 _ -> pr "int64"
8135    | RBool _ -> pr "bool"
8136    | RConstString _ -> pr "string"
8137    | RConstOptString _ -> pr "string option"
8138    | RString _ | RBufferOut _ -> pr "string"
8139    | RStringList _ -> pr "string array"
8140    | RStruct (_, typ) -> pr "%s" typ
8141    | RStructList (_, typ) -> pr "%s array" typ
8142    | RHashtable _ -> pr "(string * string) list"
8143   );
8144   if is_external then (
8145     pr " = ";
8146     if List.length (snd style) + 1 > 5 then
8147       pr "\"ocaml_guestfs_%s_byte\" " name;
8148     pr "\"ocaml_guestfs_%s\"" name
8149   );
8150   pr "\n"
8151
8152 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8153 and generate_perl_xs () =
8154   generate_header CStyle LGPLv2plus;
8155
8156   pr "\
8157 #include \"EXTERN.h\"
8158 #include \"perl.h\"
8159 #include \"XSUB.h\"
8160
8161 #include <guestfs.h>
8162
8163 #ifndef PRId64
8164 #define PRId64 \"lld\"
8165 #endif
8166
8167 static SV *
8168 my_newSVll(long long val) {
8169 #ifdef USE_64_BIT_ALL
8170   return newSViv(val);
8171 #else
8172   char buf[100];
8173   int len;
8174   len = snprintf(buf, 100, \"%%\" PRId64, val);
8175   return newSVpv(buf, len);
8176 #endif
8177 }
8178
8179 #ifndef PRIu64
8180 #define PRIu64 \"llu\"
8181 #endif
8182
8183 static SV *
8184 my_newSVull(unsigned long long val) {
8185 #ifdef USE_64_BIT_ALL
8186   return newSVuv(val);
8187 #else
8188   char buf[100];
8189   int len;
8190   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8191   return newSVpv(buf, len);
8192 #endif
8193 }
8194
8195 /* http://www.perlmonks.org/?node_id=680842 */
8196 static char **
8197 XS_unpack_charPtrPtr (SV *arg) {
8198   char **ret;
8199   AV *av;
8200   I32 i;
8201
8202   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8203     croak (\"array reference expected\");
8204
8205   av = (AV *)SvRV (arg);
8206   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8207   if (!ret)
8208     croak (\"malloc failed\");
8209
8210   for (i = 0; i <= av_len (av); i++) {
8211     SV **elem = av_fetch (av, i, 0);
8212
8213     if (!elem || !*elem)
8214       croak (\"missing element in list\");
8215
8216     ret[i] = SvPV_nolen (*elem);
8217   }
8218
8219   ret[i] = NULL;
8220
8221   return ret;
8222 }
8223
8224 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8225
8226 PROTOTYPES: ENABLE
8227
8228 guestfs_h *
8229 _create ()
8230    CODE:
8231       RETVAL = guestfs_create ();
8232       if (!RETVAL)
8233         croak (\"could not create guestfs handle\");
8234       guestfs_set_error_handler (RETVAL, NULL, NULL);
8235  OUTPUT:
8236       RETVAL
8237
8238 void
8239 DESTROY (g)
8240       guestfs_h *g;
8241  PPCODE:
8242       guestfs_close (g);
8243
8244 ";
8245
8246   List.iter (
8247     fun (name, style, _, _, _, _, _) ->
8248       (match fst style with
8249        | RErr -> pr "void\n"
8250        | RInt _ -> pr "SV *\n"
8251        | RInt64 _ -> pr "SV *\n"
8252        | RBool _ -> pr "SV *\n"
8253        | RConstString _ -> pr "SV *\n"
8254        | RConstOptString _ -> pr "SV *\n"
8255        | RString _ -> pr "SV *\n"
8256        | RBufferOut _ -> pr "SV *\n"
8257        | RStringList _
8258        | RStruct _ | RStructList _
8259        | RHashtable _ ->
8260            pr "void\n" (* all lists returned implictly on the stack *)
8261       );
8262       (* Call and arguments. *)
8263       pr "%s " name;
8264       generate_c_call_args ~handle:"g" ~decl:true style;
8265       pr "\n";
8266       pr "      guestfs_h *g;\n";
8267       iteri (
8268         fun i ->
8269           function
8270           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8271               pr "      char *%s;\n" n
8272           | OptString n ->
8273               (* http://www.perlmonks.org/?node_id=554277
8274                * Note that the implicit handle argument means we have
8275                * to add 1 to the ST(x) operator.
8276                *)
8277               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8278           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8279           | Bool n -> pr "      int %s;\n" n
8280           | Int n -> pr "      int %s;\n" n
8281           | Int64 n -> pr "      int64_t %s;\n" n
8282       ) (snd style);
8283
8284       let do_cleanups () =
8285         List.iter (
8286           function
8287           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8288           | Bool _ | Int _ | Int64 _
8289           | FileIn _ | FileOut _ -> ()
8290           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8291         ) (snd style)
8292       in
8293
8294       (* Code. *)
8295       (match fst style with
8296        | RErr ->
8297            pr "PREINIT:\n";
8298            pr "      int r;\n";
8299            pr " PPCODE:\n";
8300            pr "      r = guestfs_%s " name;
8301            generate_c_call_args ~handle:"g" style;
8302            pr ";\n";
8303            do_cleanups ();
8304            pr "      if (r == -1)\n";
8305            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8306        | RInt n
8307        | RBool n ->
8308            pr "PREINIT:\n";
8309            pr "      int %s;\n" n;
8310            pr "   CODE:\n";
8311            pr "      %s = guestfs_%s " n name;
8312            generate_c_call_args ~handle:"g" style;
8313            pr ";\n";
8314            do_cleanups ();
8315            pr "      if (%s == -1)\n" n;
8316            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8317            pr "      RETVAL = newSViv (%s);\n" n;
8318            pr " OUTPUT:\n";
8319            pr "      RETVAL\n"
8320        | RInt64 n ->
8321            pr "PREINIT:\n";
8322            pr "      int64_t %s;\n" n;
8323            pr "   CODE:\n";
8324            pr "      %s = guestfs_%s " n name;
8325            generate_c_call_args ~handle:"g" style;
8326            pr ";\n";
8327            do_cleanups ();
8328            pr "      if (%s == -1)\n" n;
8329            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8330            pr "      RETVAL = my_newSVll (%s);\n" n;
8331            pr " OUTPUT:\n";
8332            pr "      RETVAL\n"
8333        | RConstString n ->
8334            pr "PREINIT:\n";
8335            pr "      const char *%s;\n" n;
8336            pr "   CODE:\n";
8337            pr "      %s = guestfs_%s " n name;
8338            generate_c_call_args ~handle:"g" style;
8339            pr ";\n";
8340            do_cleanups ();
8341            pr "      if (%s == NULL)\n" n;
8342            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8343            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8344            pr " OUTPUT:\n";
8345            pr "      RETVAL\n"
8346        | RConstOptString n ->
8347            pr "PREINIT:\n";
8348            pr "      const char *%s;\n" n;
8349            pr "   CODE:\n";
8350            pr "      %s = guestfs_%s " n name;
8351            generate_c_call_args ~handle:"g" style;
8352            pr ";\n";
8353            do_cleanups ();
8354            pr "      if (%s == NULL)\n" n;
8355            pr "        RETVAL = &PL_sv_undef;\n";
8356            pr "      else\n";
8357            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8358            pr " OUTPUT:\n";
8359            pr "      RETVAL\n"
8360        | RString n ->
8361            pr "PREINIT:\n";
8362            pr "      char *%s;\n" n;
8363            pr "   CODE:\n";
8364            pr "      %s = guestfs_%s " n name;
8365            generate_c_call_args ~handle:"g" style;
8366            pr ";\n";
8367            do_cleanups ();
8368            pr "      if (%s == NULL)\n" n;
8369            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8370            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8371            pr "      free (%s);\n" n;
8372            pr " OUTPUT:\n";
8373            pr "      RETVAL\n"
8374        | RStringList n | RHashtable n ->
8375            pr "PREINIT:\n";
8376            pr "      char **%s;\n" n;
8377            pr "      int i, n;\n";
8378            pr " PPCODE:\n";
8379            pr "      %s = guestfs_%s " n name;
8380            generate_c_call_args ~handle:"g" style;
8381            pr ";\n";
8382            do_cleanups ();
8383            pr "      if (%s == NULL)\n" n;
8384            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8385            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8386            pr "      EXTEND (SP, n);\n";
8387            pr "      for (i = 0; i < n; ++i) {\n";
8388            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8389            pr "        free (%s[i]);\n" n;
8390            pr "      }\n";
8391            pr "      free (%s);\n" n;
8392        | RStruct (n, typ) ->
8393            let cols = cols_of_struct typ in
8394            generate_perl_struct_code typ cols name style n do_cleanups
8395        | RStructList (n, typ) ->
8396            let cols = cols_of_struct typ in
8397            generate_perl_struct_list_code typ cols name style n do_cleanups
8398        | RBufferOut n ->
8399            pr "PREINIT:\n";
8400            pr "      char *%s;\n" n;
8401            pr "      size_t size;\n";
8402            pr "   CODE:\n";
8403            pr "      %s = guestfs_%s " n name;
8404            generate_c_call_args ~handle:"g" style;
8405            pr ";\n";
8406            do_cleanups ();
8407            pr "      if (%s == NULL)\n" n;
8408            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8409            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8410            pr "      free (%s);\n" n;
8411            pr " OUTPUT:\n";
8412            pr "      RETVAL\n"
8413       );
8414
8415       pr "\n"
8416   ) all_functions
8417
8418 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8419   pr "PREINIT:\n";
8420   pr "      struct guestfs_%s_list *%s;\n" typ n;
8421   pr "      int i;\n";
8422   pr "      HV *hv;\n";
8423   pr " PPCODE:\n";
8424   pr "      %s = guestfs_%s " n name;
8425   generate_c_call_args ~handle:"g" style;
8426   pr ";\n";
8427   do_cleanups ();
8428   pr "      if (%s == NULL)\n" n;
8429   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8430   pr "      EXTEND (SP, %s->len);\n" n;
8431   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8432   pr "        hv = newHV ();\n";
8433   List.iter (
8434     function
8435     | name, FString ->
8436         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8437           name (String.length name) n name
8438     | name, FUUID ->
8439         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8440           name (String.length name) n name
8441     | name, FBuffer ->
8442         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8443           name (String.length name) n name n name
8444     | name, (FBytes|FUInt64) ->
8445         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8446           name (String.length name) n name
8447     | name, FInt64 ->
8448         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8449           name (String.length name) n name
8450     | name, (FInt32|FUInt32) ->
8451         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8452           name (String.length name) n name
8453     | name, FChar ->
8454         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8455           name (String.length name) n name
8456     | name, FOptPercent ->
8457         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8458           name (String.length name) n name
8459   ) cols;
8460   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8461   pr "      }\n";
8462   pr "      guestfs_free_%s_list (%s);\n" typ n
8463
8464 and generate_perl_struct_code typ cols name style n do_cleanups =
8465   pr "PREINIT:\n";
8466   pr "      struct guestfs_%s *%s;\n" typ n;
8467   pr " PPCODE:\n";
8468   pr "      %s = guestfs_%s " n name;
8469   generate_c_call_args ~handle:"g" style;
8470   pr ";\n";
8471   do_cleanups ();
8472   pr "      if (%s == NULL)\n" n;
8473   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8474   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8475   List.iter (
8476     fun ((name, _) as col) ->
8477       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8478
8479       match col with
8480       | name, FString ->
8481           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8482             n name
8483       | name, FBuffer ->
8484           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8485             n name n name
8486       | name, FUUID ->
8487           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8488             n name
8489       | name, (FBytes|FUInt64) ->
8490           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8491             n name
8492       | name, FInt64 ->
8493           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8494             n name
8495       | name, (FInt32|FUInt32) ->
8496           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8497             n name
8498       | name, FChar ->
8499           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8500             n name
8501       | name, FOptPercent ->
8502           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8503             n name
8504   ) cols;
8505   pr "      free (%s);\n" n
8506
8507 (* Generate Sys/Guestfs.pm. *)
8508 and generate_perl_pm () =
8509   generate_header HashStyle LGPLv2plus;
8510
8511   pr "\
8512 =pod
8513
8514 =head1 NAME
8515
8516 Sys::Guestfs - Perl bindings for libguestfs
8517
8518 =head1 SYNOPSIS
8519
8520  use Sys::Guestfs;
8521
8522  my $h = Sys::Guestfs->new ();
8523  $h->add_drive ('guest.img');
8524  $h->launch ();
8525  $h->mount ('/dev/sda1', '/');
8526  $h->touch ('/hello');
8527  $h->sync ();
8528
8529 =head1 DESCRIPTION
8530
8531 The C<Sys::Guestfs> module provides a Perl XS binding to the
8532 libguestfs API for examining and modifying virtual machine
8533 disk images.
8534
8535 Amongst the things this is good for: making batch configuration
8536 changes to guests, getting disk used/free statistics (see also:
8537 virt-df), migrating between virtualization systems (see also:
8538 virt-p2v), performing partial backups, performing partial guest
8539 clones, cloning guests and changing registry/UUID/hostname info, and
8540 much else besides.
8541
8542 Libguestfs uses Linux kernel and qemu code, and can access any type of
8543 guest filesystem that Linux and qemu can, including but not limited
8544 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8545 schemes, qcow, qcow2, vmdk.
8546
8547 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8548 LVs, what filesystem is in each LV, etc.).  It can also run commands
8549 in the context of the guest.  Also you can access filesystems over
8550 FUSE.
8551
8552 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8553 functions for using libguestfs from Perl, including integration
8554 with libvirt.
8555
8556 =head1 ERRORS
8557
8558 All errors turn into calls to C<croak> (see L<Carp(3)>).
8559
8560 =head1 METHODS
8561
8562 =over 4
8563
8564 =cut
8565
8566 package Sys::Guestfs;
8567
8568 use strict;
8569 use warnings;
8570
8571 require XSLoader;
8572 XSLoader::load ('Sys::Guestfs');
8573
8574 =item $h = Sys::Guestfs->new ();
8575
8576 Create a new guestfs handle.
8577
8578 =cut
8579
8580 sub new {
8581   my $proto = shift;
8582   my $class = ref ($proto) || $proto;
8583
8584   my $self = Sys::Guestfs::_create ();
8585   bless $self, $class;
8586   return $self;
8587 }
8588
8589 ";
8590
8591   (* Actions.  We only need to print documentation for these as
8592    * they are pulled in from the XS code automatically.
8593    *)
8594   List.iter (
8595     fun (name, style, _, flags, _, _, longdesc) ->
8596       if not (List.mem NotInDocs flags) then (
8597         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8598         pr "=item ";
8599         generate_perl_prototype name style;
8600         pr "\n\n";
8601         pr "%s\n\n" longdesc;
8602         if List.mem ProtocolLimitWarning flags then
8603           pr "%s\n\n" protocol_limit_warning;
8604         if List.mem DangerWillRobinson flags then
8605           pr "%s\n\n" danger_will_robinson;
8606         match deprecation_notice flags with
8607         | None -> ()
8608         | Some txt -> pr "%s\n\n" txt
8609       )
8610   ) all_functions_sorted;
8611
8612   (* End of file. *)
8613   pr "\
8614 =cut
8615
8616 1;
8617
8618 =back
8619
8620 =head1 COPYRIGHT
8621
8622 Copyright (C) %s Red Hat Inc.
8623
8624 =head1 LICENSE
8625
8626 Please see the file COPYING.LIB for the full license.
8627
8628 =head1 SEE ALSO
8629
8630 L<guestfs(3)>,
8631 L<guestfish(1)>,
8632 L<http://libguestfs.org>,
8633 L<Sys::Guestfs::Lib(3)>.
8634
8635 =cut
8636 " copyright_years
8637
8638 and generate_perl_prototype name style =
8639   (match fst style with
8640    | RErr -> ()
8641    | RBool n
8642    | RInt n
8643    | RInt64 n
8644    | RConstString n
8645    | RConstOptString n
8646    | RString n
8647    | RBufferOut n -> pr "$%s = " n
8648    | RStruct (n,_)
8649    | RHashtable n -> pr "%%%s = " n
8650    | RStringList n
8651    | RStructList (n,_) -> pr "@%s = " n
8652   );
8653   pr "$h->%s (" name;
8654   let comma = ref false in
8655   List.iter (
8656     fun arg ->
8657       if !comma then pr ", ";
8658       comma := true;
8659       match arg with
8660       | Pathname n | Device n | Dev_or_Path n | String n
8661       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8662           pr "$%s" n
8663       | StringList n | DeviceList n ->
8664           pr "\\@%s" n
8665   ) (snd style);
8666   pr ");"
8667
8668 (* Generate Python C module. *)
8669 and generate_python_c () =
8670   generate_header CStyle LGPLv2plus;
8671
8672   pr "\
8673 #include <Python.h>
8674
8675 #include <stdio.h>
8676 #include <stdlib.h>
8677 #include <assert.h>
8678
8679 #include \"guestfs.h\"
8680
8681 typedef struct {
8682   PyObject_HEAD
8683   guestfs_h *g;
8684 } Pyguestfs_Object;
8685
8686 static guestfs_h *
8687 get_handle (PyObject *obj)
8688 {
8689   assert (obj);
8690   assert (obj != Py_None);
8691   return ((Pyguestfs_Object *) obj)->g;
8692 }
8693
8694 static PyObject *
8695 put_handle (guestfs_h *g)
8696 {
8697   assert (g);
8698   return
8699     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8700 }
8701
8702 /* This list should be freed (but not the strings) after use. */
8703 static char **
8704 get_string_list (PyObject *obj)
8705 {
8706   int i, len;
8707   char **r;
8708
8709   assert (obj);
8710
8711   if (!PyList_Check (obj)) {
8712     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8713     return NULL;
8714   }
8715
8716   len = PyList_Size (obj);
8717   r = malloc (sizeof (char *) * (len+1));
8718   if (r == NULL) {
8719     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8720     return NULL;
8721   }
8722
8723   for (i = 0; i < len; ++i)
8724     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8725   r[len] = NULL;
8726
8727   return r;
8728 }
8729
8730 static PyObject *
8731 put_string_list (char * const * const argv)
8732 {
8733   PyObject *list;
8734   int argc, i;
8735
8736   for (argc = 0; argv[argc] != NULL; ++argc)
8737     ;
8738
8739   list = PyList_New (argc);
8740   for (i = 0; i < argc; ++i)
8741     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8742
8743   return list;
8744 }
8745
8746 static PyObject *
8747 put_table (char * const * const argv)
8748 {
8749   PyObject *list, *item;
8750   int argc, i;
8751
8752   for (argc = 0; argv[argc] != NULL; ++argc)
8753     ;
8754
8755   list = PyList_New (argc >> 1);
8756   for (i = 0; i < argc; i += 2) {
8757     item = PyTuple_New (2);
8758     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8759     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8760     PyList_SetItem (list, i >> 1, item);
8761   }
8762
8763   return list;
8764 }
8765
8766 static void
8767 free_strings (char **argv)
8768 {
8769   int argc;
8770
8771   for (argc = 0; argv[argc] != NULL; ++argc)
8772     free (argv[argc]);
8773   free (argv);
8774 }
8775
8776 static PyObject *
8777 py_guestfs_create (PyObject *self, PyObject *args)
8778 {
8779   guestfs_h *g;
8780
8781   g = guestfs_create ();
8782   if (g == NULL) {
8783     PyErr_SetString (PyExc_RuntimeError,
8784                      \"guestfs.create: failed to allocate handle\");
8785     return NULL;
8786   }
8787   guestfs_set_error_handler (g, NULL, NULL);
8788   return put_handle (g);
8789 }
8790
8791 static PyObject *
8792 py_guestfs_close (PyObject *self, PyObject *args)
8793 {
8794   PyObject *py_g;
8795   guestfs_h *g;
8796
8797   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8798     return NULL;
8799   g = get_handle (py_g);
8800
8801   guestfs_close (g);
8802
8803   Py_INCREF (Py_None);
8804   return Py_None;
8805 }
8806
8807 ";
8808
8809   let emit_put_list_function typ =
8810     pr "static PyObject *\n";
8811     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8812     pr "{\n";
8813     pr "  PyObject *list;\n";
8814     pr "  int i;\n";
8815     pr "\n";
8816     pr "  list = PyList_New (%ss->len);\n" typ;
8817     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8818     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8819     pr "  return list;\n";
8820     pr "};\n";
8821     pr "\n"
8822   in
8823
8824   (* Structures, turned into Python dictionaries. *)
8825   List.iter (
8826     fun (typ, cols) ->
8827       pr "static PyObject *\n";
8828       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8829       pr "{\n";
8830       pr "  PyObject *dict;\n";
8831       pr "\n";
8832       pr "  dict = PyDict_New ();\n";
8833       List.iter (
8834         function
8835         | name, FString ->
8836             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8837             pr "                        PyString_FromString (%s->%s));\n"
8838               typ name
8839         | name, FBuffer ->
8840             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8841             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8842               typ name typ name
8843         | name, FUUID ->
8844             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8845             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8846               typ name
8847         | name, (FBytes|FUInt64) ->
8848             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8849             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8850               typ name
8851         | name, FInt64 ->
8852             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8853             pr "                        PyLong_FromLongLong (%s->%s));\n"
8854               typ name
8855         | name, FUInt32 ->
8856             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8857             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8858               typ name
8859         | name, FInt32 ->
8860             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8861             pr "                        PyLong_FromLong (%s->%s));\n"
8862               typ name
8863         | name, FOptPercent ->
8864             pr "  if (%s->%s >= 0)\n" typ name;
8865             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8866             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8867               typ name;
8868             pr "  else {\n";
8869             pr "    Py_INCREF (Py_None);\n";
8870             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8871             pr "  }\n"
8872         | name, FChar ->
8873             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8874             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8875       ) cols;
8876       pr "  return dict;\n";
8877       pr "};\n";
8878       pr "\n";
8879
8880   ) structs;
8881
8882   (* Emit a put_TYPE_list function definition only if that function is used. *)
8883   List.iter (
8884     function
8885     | typ, (RStructListOnly | RStructAndList) ->
8886         (* generate the function for typ *)
8887         emit_put_list_function typ
8888     | typ, _ -> () (* empty *)
8889   ) (rstructs_used_by all_functions);
8890
8891   (* Python wrapper functions. *)
8892   List.iter (
8893     fun (name, style, _, _, _, _, _) ->
8894       pr "static PyObject *\n";
8895       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8896       pr "{\n";
8897
8898       pr "  PyObject *py_g;\n";
8899       pr "  guestfs_h *g;\n";
8900       pr "  PyObject *py_r;\n";
8901
8902       let error_code =
8903         match fst style with
8904         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8905         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8906         | RConstString _ | RConstOptString _ ->
8907             pr "  const char *r;\n"; "NULL"
8908         | RString _ -> pr "  char *r;\n"; "NULL"
8909         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8910         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8911         | RStructList (_, typ) ->
8912             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8913         | RBufferOut _ ->
8914             pr "  char *r;\n";
8915             pr "  size_t size;\n";
8916             "NULL" in
8917
8918       List.iter (
8919         function
8920         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8921             pr "  const char *%s;\n" n
8922         | OptString n -> pr "  const char *%s;\n" n
8923         | StringList n | DeviceList n ->
8924             pr "  PyObject *py_%s;\n" n;
8925             pr "  char **%s;\n" n
8926         | Bool n -> pr "  int %s;\n" n
8927         | Int n -> pr "  int %s;\n" n
8928         | Int64 n -> pr "  long long %s;\n" n
8929       ) (snd style);
8930
8931       pr "\n";
8932
8933       (* Convert the parameters. *)
8934       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8935       List.iter (
8936         function
8937         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8938         | OptString _ -> pr "z"
8939         | StringList _ | DeviceList _ -> pr "O"
8940         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8941         | Int _ -> pr "i"
8942         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8943                              * emulate C's int/long/long long in Python?
8944                              *)
8945       ) (snd style);
8946       pr ":guestfs_%s\",\n" name;
8947       pr "                         &py_g";
8948       List.iter (
8949         function
8950         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8951         | OptString n -> pr ", &%s" n
8952         | StringList n | DeviceList n -> pr ", &py_%s" n
8953         | Bool n -> pr ", &%s" n
8954         | Int n -> pr ", &%s" n
8955         | Int64 n -> pr ", &%s" n
8956       ) (snd style);
8957
8958       pr "))\n";
8959       pr "    return NULL;\n";
8960
8961       pr "  g = get_handle (py_g);\n";
8962       List.iter (
8963         function
8964         | Pathname _ | Device _ | Dev_or_Path _ | String _
8965         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8966         | StringList n | DeviceList n ->
8967             pr "  %s = get_string_list (py_%s);\n" n n;
8968             pr "  if (!%s) return NULL;\n" n
8969       ) (snd style);
8970
8971       pr "\n";
8972
8973       pr "  r = guestfs_%s " name;
8974       generate_c_call_args ~handle:"g" style;
8975       pr ";\n";
8976
8977       List.iter (
8978         function
8979         | Pathname _ | Device _ | Dev_or_Path _ | String _
8980         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8981         | StringList n | DeviceList n ->
8982             pr "  free (%s);\n" n
8983       ) (snd style);
8984
8985       pr "  if (r == %s) {\n" error_code;
8986       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8987       pr "    return NULL;\n";
8988       pr "  }\n";
8989       pr "\n";
8990
8991       (match fst style with
8992        | RErr ->
8993            pr "  Py_INCREF (Py_None);\n";
8994            pr "  py_r = Py_None;\n"
8995        | RInt _
8996        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8997        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8998        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8999        | RConstOptString _ ->
9000            pr "  if (r)\n";
9001            pr "    py_r = PyString_FromString (r);\n";
9002            pr "  else {\n";
9003            pr "    Py_INCREF (Py_None);\n";
9004            pr "    py_r = Py_None;\n";
9005            pr "  }\n"
9006        | RString _ ->
9007            pr "  py_r = PyString_FromString (r);\n";
9008            pr "  free (r);\n"
9009        | RStringList _ ->
9010            pr "  py_r = put_string_list (r);\n";
9011            pr "  free_strings (r);\n"
9012        | RStruct (_, typ) ->
9013            pr "  py_r = put_%s (r);\n" typ;
9014            pr "  guestfs_free_%s (r);\n" typ
9015        | RStructList (_, typ) ->
9016            pr "  py_r = put_%s_list (r);\n" typ;
9017            pr "  guestfs_free_%s_list (r);\n" typ
9018        | RHashtable n ->
9019            pr "  py_r = put_table (r);\n";
9020            pr "  free_strings (r);\n"
9021        | RBufferOut _ ->
9022            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9023            pr "  free (r);\n"
9024       );
9025
9026       pr "  return py_r;\n";
9027       pr "}\n";
9028       pr "\n"
9029   ) all_functions;
9030
9031   (* Table of functions. *)
9032   pr "static PyMethodDef methods[] = {\n";
9033   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9034   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9035   List.iter (
9036     fun (name, _, _, _, _, _, _) ->
9037       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9038         name name
9039   ) all_functions;
9040   pr "  { NULL, NULL, 0, NULL }\n";
9041   pr "};\n";
9042   pr "\n";
9043
9044   (* Init function. *)
9045   pr "\
9046 void
9047 initlibguestfsmod (void)
9048 {
9049   static int initialized = 0;
9050
9051   if (initialized) return;
9052   Py_InitModule ((char *) \"libguestfsmod\", methods);
9053   initialized = 1;
9054 }
9055 "
9056
9057 (* Generate Python module. *)
9058 and generate_python_py () =
9059   generate_header HashStyle LGPLv2plus;
9060
9061   pr "\
9062 u\"\"\"Python bindings for libguestfs
9063
9064 import guestfs
9065 g = guestfs.GuestFS ()
9066 g.add_drive (\"guest.img\")
9067 g.launch ()
9068 parts = g.list_partitions ()
9069
9070 The guestfs module provides a Python binding to the libguestfs API
9071 for examining and modifying virtual machine disk images.
9072
9073 Amongst the things this is good for: making batch configuration
9074 changes to guests, getting disk used/free statistics (see also:
9075 virt-df), migrating between virtualization systems (see also:
9076 virt-p2v), performing partial backups, performing partial guest
9077 clones, cloning guests and changing registry/UUID/hostname info, and
9078 much else besides.
9079
9080 Libguestfs uses Linux kernel and qemu code, and can access any type of
9081 guest filesystem that Linux and qemu can, including but not limited
9082 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9083 schemes, qcow, qcow2, vmdk.
9084
9085 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9086 LVs, what filesystem is in each LV, etc.).  It can also run commands
9087 in the context of the guest.  Also you can access filesystems over
9088 FUSE.
9089
9090 Errors which happen while using the API are turned into Python
9091 RuntimeError exceptions.
9092
9093 To create a guestfs handle you usually have to perform the following
9094 sequence of calls:
9095
9096 # Create the handle, call add_drive at least once, and possibly
9097 # several times if the guest has multiple block devices:
9098 g = guestfs.GuestFS ()
9099 g.add_drive (\"guest.img\")
9100
9101 # Launch the qemu subprocess and wait for it to become ready:
9102 g.launch ()
9103
9104 # Now you can issue commands, for example:
9105 logvols = g.lvs ()
9106
9107 \"\"\"
9108
9109 import libguestfsmod
9110
9111 class GuestFS:
9112     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9113
9114     def __init__ (self):
9115         \"\"\"Create a new libguestfs handle.\"\"\"
9116         self._o = libguestfsmod.create ()
9117
9118     def __del__ (self):
9119         libguestfsmod.close (self._o)
9120
9121 ";
9122
9123   List.iter (
9124     fun (name, style, _, flags, _, _, longdesc) ->
9125       pr "    def %s " name;
9126       generate_py_call_args ~handle:"self" (snd style);
9127       pr ":\n";
9128
9129       if not (List.mem NotInDocs flags) then (
9130         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9131         let doc =
9132           match fst style with
9133           | RErr | RInt _ | RInt64 _ | RBool _
9134           | RConstOptString _ | RConstString _
9135           | RString _ | RBufferOut _ -> doc
9136           | RStringList _ ->
9137               doc ^ "\n\nThis function returns a list of strings."
9138           | RStruct (_, typ) ->
9139               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9140           | RStructList (_, typ) ->
9141               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9142           | RHashtable _ ->
9143               doc ^ "\n\nThis function returns a dictionary." in
9144         let doc =
9145           if List.mem ProtocolLimitWarning flags then
9146             doc ^ "\n\n" ^ protocol_limit_warning
9147           else doc in
9148         let doc =
9149           if List.mem DangerWillRobinson flags then
9150             doc ^ "\n\n" ^ danger_will_robinson
9151           else doc in
9152         let doc =
9153           match deprecation_notice flags with
9154           | None -> doc
9155           | Some txt -> doc ^ "\n\n" ^ txt in
9156         let doc = pod2text ~width:60 name doc in
9157         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9158         let doc = String.concat "\n        " doc in
9159         pr "        u\"\"\"%s\"\"\"\n" doc;
9160       );
9161       pr "        return libguestfsmod.%s " name;
9162       generate_py_call_args ~handle:"self._o" (snd style);
9163       pr "\n";
9164       pr "\n";
9165   ) all_functions
9166
9167 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9168 and generate_py_call_args ~handle args =
9169   pr "(%s" handle;
9170   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9171   pr ")"
9172
9173 (* Useful if you need the longdesc POD text as plain text.  Returns a
9174  * list of lines.
9175  *
9176  * Because this is very slow (the slowest part of autogeneration),
9177  * we memoize the results.
9178  *)
9179 and pod2text ~width name longdesc =
9180   let key = width, name, longdesc in
9181   try Hashtbl.find pod2text_memo key
9182   with Not_found ->
9183     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9184     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9185     close_out chan;
9186     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9187     let chan = open_process_in cmd in
9188     let lines = ref [] in
9189     let rec loop i =
9190       let line = input_line chan in
9191       if i = 1 then             (* discard the first line of output *)
9192         loop (i+1)
9193       else (
9194         let line = triml line in
9195         lines := line :: !lines;
9196         loop (i+1)
9197       ) in
9198     let lines = try loop 1 with End_of_file -> List.rev !lines in
9199     unlink filename;
9200     (match close_process_in chan with
9201      | WEXITED 0 -> ()
9202      | WEXITED i ->
9203          failwithf "pod2text: process exited with non-zero status (%d)" i
9204      | WSIGNALED i | WSTOPPED i ->
9205          failwithf "pod2text: process signalled or stopped by signal %d" i
9206     );
9207     Hashtbl.add pod2text_memo key lines;
9208     pod2text_memo_updated ();
9209     lines
9210
9211 (* Generate ruby bindings. *)
9212 and generate_ruby_c () =
9213   generate_header CStyle LGPLv2plus;
9214
9215   pr "\
9216 #include <stdio.h>
9217 #include <stdlib.h>
9218
9219 #include <ruby.h>
9220
9221 #include \"guestfs.h\"
9222
9223 #include \"extconf.h\"
9224
9225 /* For Ruby < 1.9 */
9226 #ifndef RARRAY_LEN
9227 #define RARRAY_LEN(r) (RARRAY((r))->len)
9228 #endif
9229
9230 static VALUE m_guestfs;                 /* guestfs module */
9231 static VALUE c_guestfs;                 /* guestfs_h handle */
9232 static VALUE e_Error;                   /* used for all errors */
9233
9234 static void ruby_guestfs_free (void *p)
9235 {
9236   if (!p) return;
9237   guestfs_close ((guestfs_h *) p);
9238 }
9239
9240 static VALUE ruby_guestfs_create (VALUE m)
9241 {
9242   guestfs_h *g;
9243
9244   g = guestfs_create ();
9245   if (!g)
9246     rb_raise (e_Error, \"failed to create guestfs handle\");
9247
9248   /* Don't print error messages to stderr by default. */
9249   guestfs_set_error_handler (g, NULL, NULL);
9250
9251   /* Wrap it, and make sure the close function is called when the
9252    * handle goes away.
9253    */
9254   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9255 }
9256
9257 static VALUE ruby_guestfs_close (VALUE gv)
9258 {
9259   guestfs_h *g;
9260   Data_Get_Struct (gv, guestfs_h, g);
9261
9262   ruby_guestfs_free (g);
9263   DATA_PTR (gv) = NULL;
9264
9265   return Qnil;
9266 }
9267
9268 ";
9269
9270   List.iter (
9271     fun (name, style, _, _, _, _, _) ->
9272       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9273       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9274       pr ")\n";
9275       pr "{\n";
9276       pr "  guestfs_h *g;\n";
9277       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9278       pr "  if (!g)\n";
9279       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9280         name;
9281       pr "\n";
9282
9283       List.iter (
9284         function
9285         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9286             pr "  Check_Type (%sv, T_STRING);\n" n;
9287             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9288             pr "  if (!%s)\n" n;
9289             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9290             pr "              \"%s\", \"%s\");\n" n name
9291         | OptString n ->
9292             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9293         | StringList n | DeviceList n ->
9294             pr "  char **%s;\n" n;
9295             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9296             pr "  {\n";
9297             pr "    int i, len;\n";
9298             pr "    len = RARRAY_LEN (%sv);\n" n;
9299             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9300               n;
9301             pr "    for (i = 0; i < len; ++i) {\n";
9302             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9303             pr "      %s[i] = StringValueCStr (v);\n" n;
9304             pr "    }\n";
9305             pr "    %s[len] = NULL;\n" n;
9306             pr "  }\n";
9307         | Bool n ->
9308             pr "  int %s = RTEST (%sv);\n" n n
9309         | Int n ->
9310             pr "  int %s = NUM2INT (%sv);\n" n n
9311         | Int64 n ->
9312             pr "  long long %s = NUM2LL (%sv);\n" n n
9313       ) (snd style);
9314       pr "\n";
9315
9316       let error_code =
9317         match fst style with
9318         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9319         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9320         | RConstString _ | RConstOptString _ ->
9321             pr "  const char *r;\n"; "NULL"
9322         | RString _ -> pr "  char *r;\n"; "NULL"
9323         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9324         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9325         | RStructList (_, typ) ->
9326             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9327         | RBufferOut _ ->
9328             pr "  char *r;\n";
9329             pr "  size_t size;\n";
9330             "NULL" in
9331       pr "\n";
9332
9333       pr "  r = guestfs_%s " name;
9334       generate_c_call_args ~handle:"g" style;
9335       pr ";\n";
9336
9337       List.iter (
9338         function
9339         | Pathname _ | Device _ | Dev_or_Path _ | String _
9340         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9341         | StringList n | DeviceList n ->
9342             pr "  free (%s);\n" n
9343       ) (snd style);
9344
9345       pr "  if (r == %s)\n" error_code;
9346       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9347       pr "\n";
9348
9349       (match fst style with
9350        | RErr ->
9351            pr "  return Qnil;\n"
9352        | RInt _ | RBool _ ->
9353            pr "  return INT2NUM (r);\n"
9354        | RInt64 _ ->
9355            pr "  return ULL2NUM (r);\n"
9356        | RConstString _ ->
9357            pr "  return rb_str_new2 (r);\n";
9358        | RConstOptString _ ->
9359            pr "  if (r)\n";
9360            pr "    return rb_str_new2 (r);\n";
9361            pr "  else\n";
9362            pr "    return Qnil;\n";
9363        | RString _ ->
9364            pr "  VALUE rv = rb_str_new2 (r);\n";
9365            pr "  free (r);\n";
9366            pr "  return rv;\n";
9367        | RStringList _ ->
9368            pr "  int i, len = 0;\n";
9369            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9370            pr "  VALUE rv = rb_ary_new2 (len);\n";
9371            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9372            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9373            pr "    free (r[i]);\n";
9374            pr "  }\n";
9375            pr "  free (r);\n";
9376            pr "  return rv;\n"
9377        | RStruct (_, typ) ->
9378            let cols = cols_of_struct typ in
9379            generate_ruby_struct_code typ cols
9380        | RStructList (_, typ) ->
9381            let cols = cols_of_struct typ in
9382            generate_ruby_struct_list_code typ cols
9383        | RHashtable _ ->
9384            pr "  VALUE rv = rb_hash_new ();\n";
9385            pr "  int i;\n";
9386            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9387            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9388            pr "    free (r[i]);\n";
9389            pr "    free (r[i+1]);\n";
9390            pr "  }\n";
9391            pr "  free (r);\n";
9392            pr "  return rv;\n"
9393        | RBufferOut _ ->
9394            pr "  VALUE rv = rb_str_new (r, size);\n";
9395            pr "  free (r);\n";
9396            pr "  return rv;\n";
9397       );
9398
9399       pr "}\n";
9400       pr "\n"
9401   ) all_functions;
9402
9403   pr "\
9404 /* Initialize the module. */
9405 void Init__guestfs ()
9406 {
9407   m_guestfs = rb_define_module (\"Guestfs\");
9408   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9409   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9410
9411   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9412   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9413
9414 ";
9415   (* Define the rest of the methods. *)
9416   List.iter (
9417     fun (name, style, _, _, _, _, _) ->
9418       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9419       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9420   ) all_functions;
9421
9422   pr "}\n"
9423
9424 (* Ruby code to return a struct. *)
9425 and generate_ruby_struct_code typ cols =
9426   pr "  VALUE rv = rb_hash_new ();\n";
9427   List.iter (
9428     function
9429     | name, FString ->
9430         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9431     | name, FBuffer ->
9432         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9433     | name, FUUID ->
9434         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9435     | name, (FBytes|FUInt64) ->
9436         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9437     | name, FInt64 ->
9438         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9439     | name, FUInt32 ->
9440         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9441     | name, FInt32 ->
9442         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9443     | name, FOptPercent ->
9444         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9445     | name, FChar -> (* XXX wrong? *)
9446         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9447   ) cols;
9448   pr "  guestfs_free_%s (r);\n" typ;
9449   pr "  return rv;\n"
9450
9451 (* Ruby code to return a struct list. *)
9452 and generate_ruby_struct_list_code typ cols =
9453   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9454   pr "  int i;\n";
9455   pr "  for (i = 0; i < r->len; ++i) {\n";
9456   pr "    VALUE hv = rb_hash_new ();\n";
9457   List.iter (
9458     function
9459     | name, FString ->
9460         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9461     | name, FBuffer ->
9462         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
9463     | name, FUUID ->
9464         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9465     | name, (FBytes|FUInt64) ->
9466         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9467     | name, FInt64 ->
9468         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9469     | name, FUInt32 ->
9470         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9471     | name, FInt32 ->
9472         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9473     | name, FOptPercent ->
9474         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9475     | name, FChar -> (* XXX wrong? *)
9476         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9477   ) cols;
9478   pr "    rb_ary_push (rv, hv);\n";
9479   pr "  }\n";
9480   pr "  guestfs_free_%s_list (r);\n" typ;
9481   pr "  return rv;\n"
9482
9483 (* Generate Java bindings GuestFS.java file. *)
9484 and generate_java_java () =
9485   generate_header CStyle LGPLv2plus;
9486
9487   pr "\
9488 package com.redhat.et.libguestfs;
9489
9490 import java.util.HashMap;
9491 import com.redhat.et.libguestfs.LibGuestFSException;
9492 import com.redhat.et.libguestfs.PV;
9493 import com.redhat.et.libguestfs.VG;
9494 import com.redhat.et.libguestfs.LV;
9495 import com.redhat.et.libguestfs.Stat;
9496 import com.redhat.et.libguestfs.StatVFS;
9497 import com.redhat.et.libguestfs.IntBool;
9498 import com.redhat.et.libguestfs.Dirent;
9499
9500 /**
9501  * The GuestFS object is a libguestfs handle.
9502  *
9503  * @author rjones
9504  */
9505 public class GuestFS {
9506   // Load the native code.
9507   static {
9508     System.loadLibrary (\"guestfs_jni\");
9509   }
9510
9511   /**
9512    * The native guestfs_h pointer.
9513    */
9514   long g;
9515
9516   /**
9517    * Create a libguestfs handle.
9518    *
9519    * @throws LibGuestFSException
9520    */
9521   public GuestFS () throws LibGuestFSException
9522   {
9523     g = _create ();
9524   }
9525   private native long _create () throws LibGuestFSException;
9526
9527   /**
9528    * Close a libguestfs handle.
9529    *
9530    * You can also leave handles to be collected by the garbage
9531    * collector, but this method ensures that the resources used
9532    * by the handle are freed up immediately.  If you call any
9533    * other methods after closing the handle, you will get an
9534    * exception.
9535    *
9536    * @throws LibGuestFSException
9537    */
9538   public void close () throws LibGuestFSException
9539   {
9540     if (g != 0)
9541       _close (g);
9542     g = 0;
9543   }
9544   private native void _close (long g) throws LibGuestFSException;
9545
9546   public void finalize () throws LibGuestFSException
9547   {
9548     close ();
9549   }
9550
9551 ";
9552
9553   List.iter (
9554     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9555       if not (List.mem NotInDocs flags); then (
9556         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9557         let doc =
9558           if List.mem ProtocolLimitWarning flags then
9559             doc ^ "\n\n" ^ protocol_limit_warning
9560           else doc in
9561         let doc =
9562           if List.mem DangerWillRobinson flags then
9563             doc ^ "\n\n" ^ danger_will_robinson
9564           else doc in
9565         let doc =
9566           match deprecation_notice flags with
9567           | None -> doc
9568           | Some txt -> doc ^ "\n\n" ^ txt in
9569         let doc = pod2text ~width:60 name doc in
9570         let doc = List.map (            (* RHBZ#501883 *)
9571           function
9572           | "" -> "<p>"
9573           | nonempty -> nonempty
9574         ) doc in
9575         let doc = String.concat "\n   * " doc in
9576
9577         pr "  /**\n";
9578         pr "   * %s\n" shortdesc;
9579         pr "   * <p>\n";
9580         pr "   * %s\n" doc;
9581         pr "   * @throws LibGuestFSException\n";
9582         pr "   */\n";
9583         pr "  ";
9584       );
9585       generate_java_prototype ~public:true ~semicolon:false name style;
9586       pr "\n";
9587       pr "  {\n";
9588       pr "    if (g == 0)\n";
9589       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9590         name;
9591       pr "    ";
9592       if fst style <> RErr then pr "return ";
9593       pr "_%s " name;
9594       generate_java_call_args ~handle:"g" (snd style);
9595       pr ";\n";
9596       pr "  }\n";
9597       pr "  ";
9598       generate_java_prototype ~privat:true ~native:true name style;
9599       pr "\n";
9600       pr "\n";
9601   ) all_functions;
9602
9603   pr "}\n"
9604
9605 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9606 and generate_java_call_args ~handle args =
9607   pr "(%s" handle;
9608   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9609   pr ")"
9610
9611 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9612     ?(semicolon=true) name style =
9613   if privat then pr "private ";
9614   if public then pr "public ";
9615   if native then pr "native ";
9616
9617   (* return type *)
9618   (match fst style with
9619    | RErr -> pr "void ";
9620    | RInt _ -> pr "int ";
9621    | RInt64 _ -> pr "long ";
9622    | RBool _ -> pr "boolean ";
9623    | RConstString _ | RConstOptString _ | RString _
9624    | RBufferOut _ -> pr "String ";
9625    | RStringList _ -> pr "String[] ";
9626    | RStruct (_, typ) ->
9627        let name = java_name_of_struct typ in
9628        pr "%s " name;
9629    | RStructList (_, typ) ->
9630        let name = java_name_of_struct typ in
9631        pr "%s[] " name;
9632    | RHashtable _ -> pr "HashMap<String,String> ";
9633   );
9634
9635   if native then pr "_%s " name else pr "%s " name;
9636   pr "(";
9637   let needs_comma = ref false in
9638   if native then (
9639     pr "long g";
9640     needs_comma := true
9641   );
9642
9643   (* args *)
9644   List.iter (
9645     fun arg ->
9646       if !needs_comma then pr ", ";
9647       needs_comma := true;
9648
9649       match arg with
9650       | Pathname n
9651       | Device n | Dev_or_Path n
9652       | String n
9653       | OptString n
9654       | FileIn n
9655       | FileOut n ->
9656           pr "String %s" n
9657       | StringList n | DeviceList n ->
9658           pr "String[] %s" n
9659       | Bool n ->
9660           pr "boolean %s" n
9661       | Int n ->
9662           pr "int %s" n
9663       | Int64 n ->
9664           pr "long %s" n
9665   ) (snd style);
9666
9667   pr ")\n";
9668   pr "    throws LibGuestFSException";
9669   if semicolon then pr ";"
9670
9671 and generate_java_struct jtyp cols () =
9672   generate_header CStyle LGPLv2plus;
9673
9674   pr "\
9675 package com.redhat.et.libguestfs;
9676
9677 /**
9678  * Libguestfs %s structure.
9679  *
9680  * @author rjones
9681  * @see GuestFS
9682  */
9683 public class %s {
9684 " jtyp jtyp;
9685
9686   List.iter (
9687     function
9688     | name, FString
9689     | name, FUUID
9690     | name, FBuffer -> pr "  public String %s;\n" name
9691     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9692     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9693     | name, FChar -> pr "  public char %s;\n" name
9694     | name, FOptPercent ->
9695         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9696         pr "  public float %s;\n" name
9697   ) cols;
9698
9699   pr "}\n"
9700
9701 and generate_java_c () =
9702   generate_header CStyle LGPLv2plus;
9703
9704   pr "\
9705 #include <stdio.h>
9706 #include <stdlib.h>
9707 #include <string.h>
9708
9709 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9710 #include \"guestfs.h\"
9711
9712 /* Note that this function returns.  The exception is not thrown
9713  * until after the wrapper function returns.
9714  */
9715 static void
9716 throw_exception (JNIEnv *env, const char *msg)
9717 {
9718   jclass cl;
9719   cl = (*env)->FindClass (env,
9720                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9721   (*env)->ThrowNew (env, cl, msg);
9722 }
9723
9724 JNIEXPORT jlong JNICALL
9725 Java_com_redhat_et_libguestfs_GuestFS__1create
9726   (JNIEnv *env, jobject obj)
9727 {
9728   guestfs_h *g;
9729
9730   g = guestfs_create ();
9731   if (g == NULL) {
9732     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9733     return 0;
9734   }
9735   guestfs_set_error_handler (g, NULL, NULL);
9736   return (jlong) (long) g;
9737 }
9738
9739 JNIEXPORT void JNICALL
9740 Java_com_redhat_et_libguestfs_GuestFS__1close
9741   (JNIEnv *env, jobject obj, jlong jg)
9742 {
9743   guestfs_h *g = (guestfs_h *) (long) jg;
9744   guestfs_close (g);
9745 }
9746
9747 ";
9748
9749   List.iter (
9750     fun (name, style, _, _, _, _, _) ->
9751       pr "JNIEXPORT ";
9752       (match fst style with
9753        | RErr -> pr "void ";
9754        | RInt _ -> pr "jint ";
9755        | RInt64 _ -> pr "jlong ";
9756        | RBool _ -> pr "jboolean ";
9757        | RConstString _ | RConstOptString _ | RString _
9758        | RBufferOut _ -> pr "jstring ";
9759        | RStruct _ | RHashtable _ ->
9760            pr "jobject ";
9761        | RStringList _ | RStructList _ ->
9762            pr "jobjectArray ";
9763       );
9764       pr "JNICALL\n";
9765       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9766       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9767       pr "\n";
9768       pr "  (JNIEnv *env, jobject obj, jlong jg";
9769       List.iter (
9770         function
9771         | Pathname n
9772         | Device n | Dev_or_Path n
9773         | String n
9774         | OptString n
9775         | FileIn n
9776         | FileOut n ->
9777             pr ", jstring j%s" n
9778         | StringList n | DeviceList n ->
9779             pr ", jobjectArray j%s" n
9780         | Bool n ->
9781             pr ", jboolean j%s" n
9782         | Int n ->
9783             pr ", jint j%s" n
9784         | Int64 n ->
9785             pr ", jlong j%s" n
9786       ) (snd style);
9787       pr ")\n";
9788       pr "{\n";
9789       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9790       let error_code, no_ret =
9791         match fst style with
9792         | RErr -> pr "  int r;\n"; "-1", ""
9793         | RBool _
9794         | RInt _ -> pr "  int r;\n"; "-1", "0"
9795         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9796         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9797         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9798         | RString _ ->
9799             pr "  jstring jr;\n";
9800             pr "  char *r;\n"; "NULL", "NULL"
9801         | RStringList _ ->
9802             pr "  jobjectArray jr;\n";
9803             pr "  int r_len;\n";
9804             pr "  jclass cl;\n";
9805             pr "  jstring jstr;\n";
9806             pr "  char **r;\n"; "NULL", "NULL"
9807         | RStruct (_, typ) ->
9808             pr "  jobject jr;\n";
9809             pr "  jclass cl;\n";
9810             pr "  jfieldID fl;\n";
9811             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9812         | RStructList (_, typ) ->
9813             pr "  jobjectArray jr;\n";
9814             pr "  jclass cl;\n";
9815             pr "  jfieldID fl;\n";
9816             pr "  jobject jfl;\n";
9817             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9818         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9819         | RBufferOut _ ->
9820             pr "  jstring jr;\n";
9821             pr "  char *r;\n";
9822             pr "  size_t size;\n";
9823             "NULL", "NULL" in
9824       List.iter (
9825         function
9826         | Pathname n
9827         | Device n | Dev_or_Path n
9828         | String n
9829         | OptString n
9830         | FileIn n
9831         | FileOut n ->
9832             pr "  const char *%s;\n" n
9833         | StringList n | DeviceList n ->
9834             pr "  int %s_len;\n" n;
9835             pr "  const char **%s;\n" n
9836         | Bool n
9837         | Int n ->
9838             pr "  int %s;\n" n
9839         | Int64 n ->
9840             pr "  int64_t %s;\n" n
9841       ) (snd style);
9842
9843       let needs_i =
9844         (match fst style with
9845          | RStringList _ | RStructList _ -> true
9846          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9847          | RConstOptString _
9848          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9849           List.exists (function
9850                        | StringList _ -> true
9851                        | DeviceList _ -> true
9852                        | _ -> false) (snd style) in
9853       if needs_i then
9854         pr "  int i;\n";
9855
9856       pr "\n";
9857
9858       (* Get the parameters. *)
9859       List.iter (
9860         function
9861         | Pathname n
9862         | Device n | Dev_or_Path n
9863         | String n
9864         | FileIn n
9865         | FileOut n ->
9866             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9867         | OptString n ->
9868             (* This is completely undocumented, but Java null becomes
9869              * a NULL parameter.
9870              *)
9871             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9872         | StringList n | DeviceList n ->
9873             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9874             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9875             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9876             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9877               n;
9878             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9879             pr "  }\n";
9880             pr "  %s[%s_len] = NULL;\n" n n;
9881         | Bool n
9882         | Int n
9883         | Int64 n ->
9884             pr "  %s = j%s;\n" n n
9885       ) (snd style);
9886
9887       (* Make the call. *)
9888       pr "  r = guestfs_%s " name;
9889       generate_c_call_args ~handle:"g" style;
9890       pr ";\n";
9891
9892       (* Release the parameters. *)
9893       List.iter (
9894         function
9895         | Pathname n
9896         | Device n | Dev_or_Path n
9897         | String n
9898         | FileIn n
9899         | FileOut n ->
9900             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9901         | OptString n ->
9902             pr "  if (j%s)\n" n;
9903             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9904         | StringList n | DeviceList n ->
9905             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9906             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9907               n;
9908             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9909             pr "  }\n";
9910             pr "  free (%s);\n" n
9911         | Bool n
9912         | Int n
9913         | Int64 n -> ()
9914       ) (snd style);
9915
9916       (* Check for errors. *)
9917       pr "  if (r == %s) {\n" error_code;
9918       pr "    throw_exception (env, guestfs_last_error (g));\n";
9919       pr "    return %s;\n" no_ret;
9920       pr "  }\n";
9921
9922       (* Return value. *)
9923       (match fst style with
9924        | RErr -> ()
9925        | RInt _ -> pr "  return (jint) r;\n"
9926        | RBool _ -> pr "  return (jboolean) r;\n"
9927        | RInt64 _ -> pr "  return (jlong) r;\n"
9928        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9929        | RConstOptString _ ->
9930            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9931        | RString _ ->
9932            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9933            pr "  free (r);\n";
9934            pr "  return jr;\n"
9935        | RStringList _ ->
9936            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9937            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9938            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9939            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9940            pr "  for (i = 0; i < r_len; ++i) {\n";
9941            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9942            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9943            pr "    free (r[i]);\n";
9944            pr "  }\n";
9945            pr "  free (r);\n";
9946            pr "  return jr;\n"
9947        | RStruct (_, typ) ->
9948            let jtyp = java_name_of_struct typ in
9949            let cols = cols_of_struct typ in
9950            generate_java_struct_return typ jtyp cols
9951        | RStructList (_, typ) ->
9952            let jtyp = java_name_of_struct typ in
9953            let cols = cols_of_struct typ in
9954            generate_java_struct_list_return typ jtyp cols
9955        | RHashtable _ ->
9956            (* XXX *)
9957            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9958            pr "  return NULL;\n"
9959        | RBufferOut _ ->
9960            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9961            pr "  free (r);\n";
9962            pr "  return jr;\n"
9963       );
9964
9965       pr "}\n";
9966       pr "\n"
9967   ) all_functions
9968
9969 and generate_java_struct_return typ jtyp cols =
9970   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9971   pr "  jr = (*env)->AllocObject (env, cl);\n";
9972   List.iter (
9973     function
9974     | name, FString ->
9975         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9976         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9977     | name, FUUID ->
9978         pr "  {\n";
9979         pr "    char s[33];\n";
9980         pr "    memcpy (s, r->%s, 32);\n" name;
9981         pr "    s[32] = 0;\n";
9982         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9983         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9984         pr "  }\n";
9985     | name, FBuffer ->
9986         pr "  {\n";
9987         pr "    int len = r->%s_len;\n" name;
9988         pr "    char s[len+1];\n";
9989         pr "    memcpy (s, r->%s, len);\n" name;
9990         pr "    s[len] = 0;\n";
9991         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9992         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9993         pr "  }\n";
9994     | name, (FBytes|FUInt64|FInt64) ->
9995         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9996         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9997     | name, (FUInt32|FInt32) ->
9998         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9999         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10000     | name, FOptPercent ->
10001         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10002         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10003     | name, FChar ->
10004         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10005         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10006   ) cols;
10007   pr "  free (r);\n";
10008   pr "  return jr;\n"
10009
10010 and generate_java_struct_list_return typ jtyp cols =
10011   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10012   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10013   pr "  for (i = 0; i < r->len; ++i) {\n";
10014   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10015   List.iter (
10016     function
10017     | name, FString ->
10018         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10019         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10020     | name, FUUID ->
10021         pr "    {\n";
10022         pr "      char s[33];\n";
10023         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10024         pr "      s[32] = 0;\n";
10025         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10026         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10027         pr "    }\n";
10028     | name, FBuffer ->
10029         pr "    {\n";
10030         pr "      int len = r->val[i].%s_len;\n" name;
10031         pr "      char s[len+1];\n";
10032         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10033         pr "      s[len] = 0;\n";
10034         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10035         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10036         pr "    }\n";
10037     | name, (FBytes|FUInt64|FInt64) ->
10038         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10039         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10040     | name, (FUInt32|FInt32) ->
10041         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10042         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10043     | name, FOptPercent ->
10044         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10045         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10046     | name, FChar ->
10047         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10048         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10049   ) cols;
10050   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10051   pr "  }\n";
10052   pr "  guestfs_free_%s_list (r);\n" typ;
10053   pr "  return jr;\n"
10054
10055 and generate_java_makefile_inc () =
10056   generate_header HashStyle GPLv2plus;
10057
10058   pr "java_built_sources = \\\n";
10059   List.iter (
10060     fun (typ, jtyp) ->
10061         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10062   ) java_structs;
10063   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10064
10065 and generate_haskell_hs () =
10066   generate_header HaskellStyle LGPLv2plus;
10067
10068   (* XXX We only know how to generate partial FFI for Haskell
10069    * at the moment.  Please help out!
10070    *)
10071   let can_generate style =
10072     match style with
10073     | RErr, _
10074     | RInt _, _
10075     | RInt64 _, _ -> true
10076     | RBool _, _
10077     | RConstString _, _
10078     | RConstOptString _, _
10079     | RString _, _
10080     | RStringList _, _
10081     | RStruct _, _
10082     | RStructList _, _
10083     | RHashtable _, _
10084     | RBufferOut _, _ -> false in
10085
10086   pr "\
10087 {-# INCLUDE <guestfs.h> #-}
10088 {-# LANGUAGE ForeignFunctionInterface #-}
10089
10090 module Guestfs (
10091   create";
10092
10093   (* List out the names of the actions we want to export. *)
10094   List.iter (
10095     fun (name, style, _, _, _, _, _) ->
10096       if can_generate style then pr ",\n  %s" name
10097   ) all_functions;
10098
10099   pr "
10100   ) where
10101
10102 -- Unfortunately some symbols duplicate ones already present
10103 -- in Prelude.  We don't know which, so we hard-code a list
10104 -- here.
10105 import Prelude hiding (truncate)
10106
10107 import Foreign
10108 import Foreign.C
10109 import Foreign.C.Types
10110 import IO
10111 import Control.Exception
10112 import Data.Typeable
10113
10114 data GuestfsS = GuestfsS            -- represents the opaque C struct
10115 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10116 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10117
10118 -- XXX define properly later XXX
10119 data PV = PV
10120 data VG = VG
10121 data LV = LV
10122 data IntBool = IntBool
10123 data Stat = Stat
10124 data StatVFS = StatVFS
10125 data Hashtable = Hashtable
10126
10127 foreign import ccall unsafe \"guestfs_create\" c_create
10128   :: IO GuestfsP
10129 foreign import ccall unsafe \"&guestfs_close\" c_close
10130   :: FunPtr (GuestfsP -> IO ())
10131 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10132   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10133
10134 create :: IO GuestfsH
10135 create = do
10136   p <- c_create
10137   c_set_error_handler p nullPtr nullPtr
10138   h <- newForeignPtr c_close p
10139   return h
10140
10141 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10142   :: GuestfsP -> IO CString
10143
10144 -- last_error :: GuestfsH -> IO (Maybe String)
10145 -- last_error h = do
10146 --   str <- withForeignPtr h (\\p -> c_last_error p)
10147 --   maybePeek peekCString str
10148
10149 last_error :: GuestfsH -> IO (String)
10150 last_error h = do
10151   str <- withForeignPtr h (\\p -> c_last_error p)
10152   if (str == nullPtr)
10153     then return \"no error\"
10154     else peekCString str
10155
10156 ";
10157
10158   (* Generate wrappers for each foreign function. *)
10159   List.iter (
10160     fun (name, style, _, _, _, _, _) ->
10161       if can_generate style then (
10162         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10163         pr "  :: ";
10164         generate_haskell_prototype ~handle:"GuestfsP" style;
10165         pr "\n";
10166         pr "\n";
10167         pr "%s :: " name;
10168         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10169         pr "\n";
10170         pr "%s %s = do\n" name
10171           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10172         pr "  r <- ";
10173         (* Convert pointer arguments using with* functions. *)
10174         List.iter (
10175           function
10176           | FileIn n
10177           | FileOut n
10178           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10179           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10180           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10181           | Bool _ | Int _ | Int64 _ -> ()
10182         ) (snd style);
10183         (* Convert integer arguments. *)
10184         let args =
10185           List.map (
10186             function
10187             | Bool n -> sprintf "(fromBool %s)" n
10188             | Int n -> sprintf "(fromIntegral %s)" n
10189             | Int64 n -> sprintf "(fromIntegral %s)" n
10190             | FileIn n | FileOut n
10191             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10192           ) (snd style) in
10193         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10194           (String.concat " " ("p" :: args));
10195         (match fst style with
10196          | RErr | RInt _ | RInt64 _ | RBool _ ->
10197              pr "  if (r == -1)\n";
10198              pr "    then do\n";
10199              pr "      err <- last_error h\n";
10200              pr "      fail err\n";
10201          | RConstString _ | RConstOptString _ | RString _
10202          | RStringList _ | RStruct _
10203          | RStructList _ | RHashtable _ | RBufferOut _ ->
10204              pr "  if (r == nullPtr)\n";
10205              pr "    then do\n";
10206              pr "      err <- last_error h\n";
10207              pr "      fail err\n";
10208         );
10209         (match fst style with
10210          | RErr ->
10211              pr "    else return ()\n"
10212          | RInt _ ->
10213              pr "    else return (fromIntegral r)\n"
10214          | RInt64 _ ->
10215              pr "    else return (fromIntegral r)\n"
10216          | RBool _ ->
10217              pr "    else return (toBool r)\n"
10218          | RConstString _
10219          | RConstOptString _
10220          | RString _
10221          | RStringList _
10222          | RStruct _
10223          | RStructList _
10224          | RHashtable _
10225          | RBufferOut _ ->
10226              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10227         );
10228         pr "\n";
10229       )
10230   ) all_functions
10231
10232 and generate_haskell_prototype ~handle ?(hs = false) style =
10233   pr "%s -> " handle;
10234   let string = if hs then "String" else "CString" in
10235   let int = if hs then "Int" else "CInt" in
10236   let bool = if hs then "Bool" else "CInt" in
10237   let int64 = if hs then "Integer" else "Int64" in
10238   List.iter (
10239     fun arg ->
10240       (match arg with
10241        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10242        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10243        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10244        | Bool _ -> pr "%s" bool
10245        | Int _ -> pr "%s" int
10246        | Int64 _ -> pr "%s" int
10247        | FileIn _ -> pr "%s" string
10248        | FileOut _ -> pr "%s" string
10249       );
10250       pr " -> ";
10251   ) (snd style);
10252   pr "IO (";
10253   (match fst style with
10254    | RErr -> if not hs then pr "CInt"
10255    | RInt _ -> pr "%s" int
10256    | RInt64 _ -> pr "%s" int64
10257    | RBool _ -> pr "%s" bool
10258    | RConstString _ -> pr "%s" string
10259    | RConstOptString _ -> pr "Maybe %s" string
10260    | RString _ -> pr "%s" string
10261    | RStringList _ -> pr "[%s]" string
10262    | RStruct (_, typ) ->
10263        let name = java_name_of_struct typ in
10264        pr "%s" name
10265    | RStructList (_, typ) ->
10266        let name = java_name_of_struct typ in
10267        pr "[%s]" name
10268    | RHashtable _ -> pr "Hashtable"
10269    | RBufferOut _ -> pr "%s" string
10270   );
10271   pr ")"
10272
10273 and generate_csharp () =
10274   generate_header CPlusPlusStyle LGPLv2plus;
10275
10276   (* XXX Make this configurable by the C# assembly users. *)
10277   let library = "libguestfs.so.0" in
10278
10279   pr "\
10280 // These C# bindings are highly experimental at present.
10281 //
10282 // Firstly they only work on Linux (ie. Mono).  In order to get them
10283 // to work on Windows (ie. .Net) you would need to port the library
10284 // itself to Windows first.
10285 //
10286 // The second issue is that some calls are known to be incorrect and
10287 // can cause Mono to segfault.  Particularly: calls which pass or
10288 // return string[], or return any structure value.  This is because
10289 // we haven't worked out the correct way to do this from C#.
10290 //
10291 // The third issue is that when compiling you get a lot of warnings.
10292 // We are not sure whether the warnings are important or not.
10293 //
10294 // Fourthly we do not routinely build or test these bindings as part
10295 // of the make && make check cycle, which means that regressions might
10296 // go unnoticed.
10297 //
10298 // Suggestions and patches are welcome.
10299
10300 // To compile:
10301 //
10302 // gmcs Libguestfs.cs
10303 // mono Libguestfs.exe
10304 //
10305 // (You'll probably want to add a Test class / static main function
10306 // otherwise this won't do anything useful).
10307
10308 using System;
10309 using System.IO;
10310 using System.Runtime.InteropServices;
10311 using System.Runtime.Serialization;
10312 using System.Collections;
10313
10314 namespace Guestfs
10315 {
10316   class Error : System.ApplicationException
10317   {
10318     public Error (string message) : base (message) {}
10319     protected Error (SerializationInfo info, StreamingContext context) {}
10320   }
10321
10322   class Guestfs
10323   {
10324     IntPtr _handle;
10325
10326     [DllImport (\"%s\")]
10327     static extern IntPtr guestfs_create ();
10328
10329     public Guestfs ()
10330     {
10331       _handle = guestfs_create ();
10332       if (_handle == IntPtr.Zero)
10333         throw new Error (\"could not create guestfs handle\");
10334     }
10335
10336     [DllImport (\"%s\")]
10337     static extern void guestfs_close (IntPtr h);
10338
10339     ~Guestfs ()
10340     {
10341       guestfs_close (_handle);
10342     }
10343
10344     [DllImport (\"%s\")]
10345     static extern string guestfs_last_error (IntPtr h);
10346
10347 " library library library;
10348
10349   (* Generate C# structure bindings.  We prefix struct names with
10350    * underscore because C# cannot have conflicting struct names and
10351    * method names (eg. "class stat" and "stat").
10352    *)
10353   List.iter (
10354     fun (typ, cols) ->
10355       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10356       pr "    public class _%s {\n" typ;
10357       List.iter (
10358         function
10359         | name, FChar -> pr "      char %s;\n" name
10360         | name, FString -> pr "      string %s;\n" name
10361         | name, FBuffer ->
10362             pr "      uint %s_len;\n" name;
10363             pr "      string %s;\n" name
10364         | name, FUUID ->
10365             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10366             pr "      string %s;\n" name
10367         | name, FUInt32 -> pr "      uint %s;\n" name
10368         | name, FInt32 -> pr "      int %s;\n" name
10369         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10370         | name, FInt64 -> pr "      long %s;\n" name
10371         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10372       ) cols;
10373       pr "    }\n";
10374       pr "\n"
10375   ) structs;
10376
10377   (* Generate C# function bindings. *)
10378   List.iter (
10379     fun (name, style, _, _, _, shortdesc, _) ->
10380       let rec csharp_return_type () =
10381         match fst style with
10382         | RErr -> "void"
10383         | RBool n -> "bool"
10384         | RInt n -> "int"
10385         | RInt64 n -> "long"
10386         | RConstString n
10387         | RConstOptString n
10388         | RString n
10389         | RBufferOut n -> "string"
10390         | RStruct (_,n) -> "_" ^ n
10391         | RHashtable n -> "Hashtable"
10392         | RStringList n -> "string[]"
10393         | RStructList (_,n) -> sprintf "_%s[]" n
10394
10395       and c_return_type () =
10396         match fst style with
10397         | RErr
10398         | RBool _
10399         | RInt _ -> "int"
10400         | RInt64 _ -> "long"
10401         | RConstString _
10402         | RConstOptString _
10403         | RString _
10404         | RBufferOut _ -> "string"
10405         | RStruct (_,n) -> "_" ^ n
10406         | RHashtable _
10407         | RStringList _ -> "string[]"
10408         | RStructList (_,n) -> sprintf "_%s[]" n
10409
10410       and c_error_comparison () =
10411         match fst style with
10412         | RErr
10413         | RBool _
10414         | RInt _
10415         | RInt64 _ -> "== -1"
10416         | RConstString _
10417         | RConstOptString _
10418         | RString _
10419         | RBufferOut _
10420         | RStruct (_,_)
10421         | RHashtable _
10422         | RStringList _
10423         | RStructList (_,_) -> "== null"
10424
10425       and generate_extern_prototype () =
10426         pr "    static extern %s guestfs_%s (IntPtr h"
10427           (c_return_type ()) name;
10428         List.iter (
10429           function
10430           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10431           | FileIn n | FileOut n ->
10432               pr ", [In] string %s" n
10433           | StringList n | DeviceList n ->
10434               pr ", [In] string[] %s" n
10435           | Bool n ->
10436               pr ", bool %s" n
10437           | Int n ->
10438               pr ", int %s" n
10439           | Int64 n ->
10440               pr ", long %s" n
10441         ) (snd style);
10442         pr ");\n"
10443
10444       and generate_public_prototype () =
10445         pr "    public %s %s (" (csharp_return_type ()) name;
10446         let comma = ref false in
10447         let next () =
10448           if !comma then pr ", ";
10449           comma := true
10450         in
10451         List.iter (
10452           function
10453           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10454           | FileIn n | FileOut n ->
10455               next (); pr "string %s" n
10456           | StringList n | DeviceList n ->
10457               next (); pr "string[] %s" n
10458           | Bool n ->
10459               next (); pr "bool %s" n
10460           | Int n ->
10461               next (); pr "int %s" n
10462           | Int64 n ->
10463               next (); pr "long %s" n
10464         ) (snd style);
10465         pr ")\n"
10466
10467       and generate_call () =
10468         pr "guestfs_%s (_handle" name;
10469         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10470         pr ");\n";
10471       in
10472
10473       pr "    [DllImport (\"%s\")]\n" library;
10474       generate_extern_prototype ();
10475       pr "\n";
10476       pr "    /// <summary>\n";
10477       pr "    /// %s\n" shortdesc;
10478       pr "    /// </summary>\n";
10479       generate_public_prototype ();
10480       pr "    {\n";
10481       pr "      %s r;\n" (c_return_type ());
10482       pr "      r = ";
10483       generate_call ();
10484       pr "      if (r %s)\n" (c_error_comparison ());
10485       pr "        throw new Error (guestfs_last_error (_handle));\n";
10486       (match fst style with
10487        | RErr -> ()
10488        | RBool _ ->
10489            pr "      return r != 0 ? true : false;\n"
10490        | RHashtable _ ->
10491            pr "      Hashtable rr = new Hashtable ();\n";
10492            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10493            pr "        rr.Add (r[i], r[i+1]);\n";
10494            pr "      return rr;\n"
10495        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10496        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10497        | RStructList _ ->
10498            pr "      return r;\n"
10499       );
10500       pr "    }\n";
10501       pr "\n";
10502   ) all_functions_sorted;
10503
10504   pr "  }
10505 }
10506 "
10507
10508 and generate_bindtests () =
10509   generate_header CStyle LGPLv2plus;
10510
10511   pr "\
10512 #include <stdio.h>
10513 #include <stdlib.h>
10514 #include <inttypes.h>
10515 #include <string.h>
10516
10517 #include \"guestfs.h\"
10518 #include \"guestfs-internal.h\"
10519 #include \"guestfs-internal-actions.h\"
10520 #include \"guestfs_protocol.h\"
10521
10522 #define error guestfs_error
10523 #define safe_calloc guestfs_safe_calloc
10524 #define safe_malloc guestfs_safe_malloc
10525
10526 static void
10527 print_strings (char *const *argv)
10528 {
10529   int argc;
10530
10531   printf (\"[\");
10532   for (argc = 0; argv[argc] != NULL; ++argc) {
10533     if (argc > 0) printf (\", \");
10534     printf (\"\\\"%%s\\\"\", argv[argc]);
10535   }
10536   printf (\"]\\n\");
10537 }
10538
10539 /* The test0 function prints its parameters to stdout. */
10540 ";
10541
10542   let test0, tests =
10543     match test_functions with
10544     | [] -> assert false
10545     | test0 :: tests -> test0, tests in
10546
10547   let () =
10548     let (name, style, _, _, _, _, _) = test0 in
10549     generate_prototype ~extern:false ~semicolon:false ~newline:true
10550       ~handle:"g" ~prefix:"guestfs__" name style;
10551     pr "{\n";
10552     List.iter (
10553       function
10554       | Pathname n
10555       | Device n | Dev_or_Path n
10556       | String n
10557       | FileIn n
10558       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10559       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10560       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10561       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10562       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10563       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10564     ) (snd style);
10565     pr "  /* Java changes stdout line buffering so we need this: */\n";
10566     pr "  fflush (stdout);\n";
10567     pr "  return 0;\n";
10568     pr "}\n";
10569     pr "\n" in
10570
10571   List.iter (
10572     fun (name, style, _, _, _, _, _) ->
10573       if String.sub name (String.length name - 3) 3 <> "err" then (
10574         pr "/* Test normal return. */\n";
10575         generate_prototype ~extern:false ~semicolon:false ~newline:true
10576           ~handle:"g" ~prefix:"guestfs__" name style;
10577         pr "{\n";
10578         (match fst style with
10579          | RErr ->
10580              pr "  return 0;\n"
10581          | RInt _ ->
10582              pr "  int r;\n";
10583              pr "  sscanf (val, \"%%d\", &r);\n";
10584              pr "  return r;\n"
10585          | RInt64 _ ->
10586              pr "  int64_t r;\n";
10587              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10588              pr "  return r;\n"
10589          | RBool _ ->
10590              pr "  return STREQ (val, \"true\");\n"
10591          | RConstString _
10592          | RConstOptString _ ->
10593              (* Can't return the input string here.  Return a static
10594               * string so we ensure we get a segfault if the caller
10595               * tries to free it.
10596               *)
10597              pr "  return \"static string\";\n"
10598          | RString _ ->
10599              pr "  return strdup (val);\n"
10600          | RStringList _ ->
10601              pr "  char **strs;\n";
10602              pr "  int n, i;\n";
10603              pr "  sscanf (val, \"%%d\", &n);\n";
10604              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10605              pr "  for (i = 0; i < n; ++i) {\n";
10606              pr "    strs[i] = safe_malloc (g, 16);\n";
10607              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10608              pr "  }\n";
10609              pr "  strs[n] = NULL;\n";
10610              pr "  return strs;\n"
10611          | RStruct (_, typ) ->
10612              pr "  struct guestfs_%s *r;\n" typ;
10613              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10614              pr "  return r;\n"
10615          | RStructList (_, typ) ->
10616              pr "  struct guestfs_%s_list *r;\n" typ;
10617              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10618              pr "  sscanf (val, \"%%d\", &r->len);\n";
10619              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10620              pr "  return r;\n"
10621          | RHashtable _ ->
10622              pr "  char **strs;\n";
10623              pr "  int n, i;\n";
10624              pr "  sscanf (val, \"%%d\", &n);\n";
10625              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10626              pr "  for (i = 0; i < n; ++i) {\n";
10627              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10628              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10629              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10630              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10631              pr "  }\n";
10632              pr "  strs[n*2] = NULL;\n";
10633              pr "  return strs;\n"
10634          | RBufferOut _ ->
10635              pr "  return strdup (val);\n"
10636         );
10637         pr "}\n";
10638         pr "\n"
10639       ) else (
10640         pr "/* Test error return. */\n";
10641         generate_prototype ~extern:false ~semicolon:false ~newline:true
10642           ~handle:"g" ~prefix:"guestfs__" name style;
10643         pr "{\n";
10644         pr "  error (g, \"error\");\n";
10645         (match fst style with
10646          | RErr | RInt _ | RInt64 _ | RBool _ ->
10647              pr "  return -1;\n"
10648          | RConstString _ | RConstOptString _
10649          | RString _ | RStringList _ | RStruct _
10650          | RStructList _
10651          | RHashtable _
10652          | RBufferOut _ ->
10653              pr "  return NULL;\n"
10654         );
10655         pr "}\n";
10656         pr "\n"
10657       )
10658   ) tests
10659
10660 and generate_ocaml_bindtests () =
10661   generate_header OCamlStyle GPLv2plus;
10662
10663   pr "\
10664 let () =
10665   let g = Guestfs.create () in
10666 ";
10667
10668   let mkargs args =
10669     String.concat " " (
10670       List.map (
10671         function
10672         | CallString s -> "\"" ^ s ^ "\""
10673         | CallOptString None -> "None"
10674         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10675         | CallStringList xs ->
10676             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10677         | CallInt i when i >= 0 -> string_of_int i
10678         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10679         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10680         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10681         | CallBool b -> string_of_bool b
10682       ) args
10683     )
10684   in
10685
10686   generate_lang_bindtests (
10687     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10688   );
10689
10690   pr "print_endline \"EOF\"\n"
10691
10692 and generate_perl_bindtests () =
10693   pr "#!/usr/bin/perl -w\n";
10694   generate_header HashStyle GPLv2plus;
10695
10696   pr "\
10697 use strict;
10698
10699 use Sys::Guestfs;
10700
10701 my $g = Sys::Guestfs->new ();
10702 ";
10703
10704   let mkargs args =
10705     String.concat ", " (
10706       List.map (
10707         function
10708         | CallString s -> "\"" ^ s ^ "\""
10709         | CallOptString None -> "undef"
10710         | CallOptString (Some s) -> sprintf "\"%s\"" s
10711         | CallStringList xs ->
10712             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10713         | CallInt i -> string_of_int i
10714         | CallInt64 i -> Int64.to_string i
10715         | CallBool b -> if b then "1" else "0"
10716       ) args
10717     )
10718   in
10719
10720   generate_lang_bindtests (
10721     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10722   );
10723
10724   pr "print \"EOF\\n\"\n"
10725
10726 and generate_python_bindtests () =
10727   generate_header HashStyle GPLv2plus;
10728
10729   pr "\
10730 import guestfs
10731
10732 g = guestfs.GuestFS ()
10733 ";
10734
10735   let mkargs args =
10736     String.concat ", " (
10737       List.map (
10738         function
10739         | CallString s -> "\"" ^ s ^ "\""
10740         | CallOptString None -> "None"
10741         | CallOptString (Some s) -> sprintf "\"%s\"" s
10742         | CallStringList xs ->
10743             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10744         | CallInt i -> string_of_int i
10745         | CallInt64 i -> Int64.to_string i
10746         | CallBool b -> if b then "1" else "0"
10747       ) args
10748     )
10749   in
10750
10751   generate_lang_bindtests (
10752     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10753   );
10754
10755   pr "print \"EOF\"\n"
10756
10757 and generate_ruby_bindtests () =
10758   generate_header HashStyle GPLv2plus;
10759
10760   pr "\
10761 require 'guestfs'
10762
10763 g = Guestfs::create()
10764 ";
10765
10766   let mkargs args =
10767     String.concat ", " (
10768       List.map (
10769         function
10770         | CallString s -> "\"" ^ s ^ "\""
10771         | CallOptString None -> "nil"
10772         | CallOptString (Some s) -> sprintf "\"%s\"" s
10773         | CallStringList xs ->
10774             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10775         | CallInt i -> string_of_int i
10776         | CallInt64 i -> Int64.to_string i
10777         | CallBool b -> string_of_bool b
10778       ) args
10779     )
10780   in
10781
10782   generate_lang_bindtests (
10783     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10784   );
10785
10786   pr "print \"EOF\\n\"\n"
10787
10788 and generate_java_bindtests () =
10789   generate_header CStyle GPLv2plus;
10790
10791   pr "\
10792 import com.redhat.et.libguestfs.*;
10793
10794 public class Bindtests {
10795     public static void main (String[] argv)
10796     {
10797         try {
10798             GuestFS g = new GuestFS ();
10799 ";
10800
10801   let mkargs args =
10802     String.concat ", " (
10803       List.map (
10804         function
10805         | CallString s -> "\"" ^ s ^ "\""
10806         | CallOptString None -> "null"
10807         | CallOptString (Some s) -> sprintf "\"%s\"" s
10808         | CallStringList xs ->
10809             "new String[]{" ^
10810               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10811         | CallInt i -> string_of_int i
10812         | CallInt64 i -> Int64.to_string i
10813         | CallBool b -> string_of_bool b
10814       ) args
10815     )
10816   in
10817
10818   generate_lang_bindtests (
10819     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10820   );
10821
10822   pr "
10823             System.out.println (\"EOF\");
10824         }
10825         catch (Exception exn) {
10826             System.err.println (exn);
10827             System.exit (1);
10828         }
10829     }
10830 }
10831 "
10832
10833 and generate_haskell_bindtests () =
10834   generate_header HaskellStyle GPLv2plus;
10835
10836   pr "\
10837 module Bindtests where
10838 import qualified Guestfs
10839
10840 main = do
10841   g <- Guestfs.create
10842 ";
10843
10844   let mkargs args =
10845     String.concat " " (
10846       List.map (
10847         function
10848         | CallString s -> "\"" ^ s ^ "\""
10849         | CallOptString None -> "Nothing"
10850         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10851         | CallStringList xs ->
10852             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10853         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10854         | CallInt i -> string_of_int i
10855         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10856         | CallInt64 i -> Int64.to_string i
10857         | CallBool true -> "True"
10858         | CallBool false -> "False"
10859       ) args
10860     )
10861   in
10862
10863   generate_lang_bindtests (
10864     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10865   );
10866
10867   pr "  putStrLn \"EOF\"\n"
10868
10869 (* Language-independent bindings tests - we do it this way to
10870  * ensure there is parity in testing bindings across all languages.
10871  *)
10872 and generate_lang_bindtests call =
10873   call "test0" [CallString "abc"; CallOptString (Some "def");
10874                 CallStringList []; CallBool false;
10875                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10876   call "test0" [CallString "abc"; CallOptString None;
10877                 CallStringList []; CallBool false;
10878                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10879   call "test0" [CallString ""; CallOptString (Some "def");
10880                 CallStringList []; CallBool false;
10881                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10882   call "test0" [CallString ""; CallOptString (Some "");
10883                 CallStringList []; CallBool false;
10884                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10885   call "test0" [CallString "abc"; CallOptString (Some "def");
10886                 CallStringList ["1"]; CallBool false;
10887                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10888   call "test0" [CallString "abc"; CallOptString (Some "def");
10889                 CallStringList ["1"; "2"]; CallBool false;
10890                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10891   call "test0" [CallString "abc"; CallOptString (Some "def");
10892                 CallStringList ["1"]; CallBool true;
10893                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10894   call "test0" [CallString "abc"; CallOptString (Some "def");
10895                 CallStringList ["1"]; CallBool false;
10896                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10897   call "test0" [CallString "abc"; CallOptString (Some "def");
10898                 CallStringList ["1"]; CallBool false;
10899                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10900   call "test0" [CallString "abc"; CallOptString (Some "def");
10901                 CallStringList ["1"]; CallBool false;
10902                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10903   call "test0" [CallString "abc"; CallOptString (Some "def");
10904                 CallStringList ["1"]; CallBool false;
10905                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10906   call "test0" [CallString "abc"; CallOptString (Some "def");
10907                 CallStringList ["1"]; CallBool false;
10908                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10909   call "test0" [CallString "abc"; CallOptString (Some "def");
10910                 CallStringList ["1"]; CallBool false;
10911                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10912
10913 (* XXX Add here tests of the return and error functions. *)
10914
10915 (* Code to generator bindings for virt-inspector.  Currently only
10916  * implemented for OCaml code (for virt-p2v 2.0).
10917  *)
10918 let rng_input = "inspector/virt-inspector.rng"
10919
10920 (* Read the input file and parse it into internal structures.  This is
10921  * by no means a complete RELAX NG parser, but is just enough to be
10922  * able to parse the specific input file.
10923  *)
10924 type rng =
10925   | Element of string * rng list        (* <element name=name/> *)
10926   | Attribute of string * rng list        (* <attribute name=name/> *)
10927   | Interleave of rng list                (* <interleave/> *)
10928   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10929   | OneOrMore of rng                        (* <oneOrMore/> *)
10930   | Optional of rng                        (* <optional/> *)
10931   | Choice of string list                (* <choice><value/>*</choice> *)
10932   | Value of string                        (* <value>str</value> *)
10933   | Text                                (* <text/> *)
10934
10935 let rec string_of_rng = function
10936   | Element (name, xs) ->
10937       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10938   | Attribute (name, xs) ->
10939       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10940   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10941   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10942   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10943   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10944   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10945   | Value value -> "Value \"" ^ value ^ "\""
10946   | Text -> "Text"
10947
10948 and string_of_rng_list xs =
10949   String.concat ", " (List.map string_of_rng xs)
10950
10951 let rec parse_rng ?defines context = function
10952   | [] -> []
10953   | Xml.Element ("element", ["name", name], children) :: rest ->
10954       Element (name, parse_rng ?defines context children)
10955       :: parse_rng ?defines context rest
10956   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10957       Attribute (name, parse_rng ?defines context children)
10958       :: parse_rng ?defines context rest
10959   | Xml.Element ("interleave", [], children) :: rest ->
10960       Interleave (parse_rng ?defines context children)
10961       :: parse_rng ?defines context rest
10962   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10963       let rng = parse_rng ?defines context [child] in
10964       (match rng with
10965        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10966        | _ ->
10967            failwithf "%s: <zeroOrMore> contains more than one child element"
10968              context
10969       )
10970   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10971       let rng = parse_rng ?defines context [child] in
10972       (match rng with
10973        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10974        | _ ->
10975            failwithf "%s: <oneOrMore> contains more than one child element"
10976              context
10977       )
10978   | Xml.Element ("optional", [], [child]) :: rest ->
10979       let rng = parse_rng ?defines context [child] in
10980       (match rng with
10981        | [child] -> Optional child :: parse_rng ?defines context rest
10982        | _ ->
10983            failwithf "%s: <optional> contains more than one child element"
10984              context
10985       )
10986   | Xml.Element ("choice", [], children) :: rest ->
10987       let values = List.map (
10988         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10989         | _ ->
10990             failwithf "%s: can't handle anything except <value> in <choice>"
10991               context
10992       ) children in
10993       Choice values
10994       :: parse_rng ?defines context rest
10995   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10996       Value value :: parse_rng ?defines context rest
10997   | Xml.Element ("text", [], []) :: rest ->
10998       Text :: parse_rng ?defines context rest
10999   | Xml.Element ("ref", ["name", name], []) :: rest ->
11000       (* Look up the reference.  Because of limitations in this parser,
11001        * we can't handle arbitrarily nested <ref> yet.  You can only
11002        * use <ref> from inside <start>.
11003        *)
11004       (match defines with
11005        | None ->
11006            failwithf "%s: contains <ref>, but no refs are defined yet" context
11007        | Some map ->
11008            let rng = StringMap.find name map in
11009            rng @ parse_rng ?defines context rest
11010       )
11011   | x :: _ ->
11012       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11013
11014 let grammar =
11015   let xml = Xml.parse_file rng_input in
11016   match xml with
11017   | Xml.Element ("grammar", _,
11018                  Xml.Element ("start", _, gram) :: defines) ->
11019       (* The <define/> elements are referenced in the <start> section,
11020        * so build a map of those first.
11021        *)
11022       let defines = List.fold_left (
11023         fun map ->
11024           function Xml.Element ("define", ["name", name], defn) ->
11025             StringMap.add name defn map
11026           | _ ->
11027               failwithf "%s: expected <define name=name/>" rng_input
11028       ) StringMap.empty defines in
11029       let defines = StringMap.mapi parse_rng defines in
11030
11031       (* Parse the <start> clause, passing the defines. *)
11032       parse_rng ~defines "<start>" gram
11033   | _ ->
11034       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11035         rng_input
11036
11037 let name_of_field = function
11038   | Element (name, _) | Attribute (name, _)
11039   | ZeroOrMore (Element (name, _))
11040   | OneOrMore (Element (name, _))
11041   | Optional (Element (name, _)) -> name
11042   | Optional (Attribute (name, _)) -> name
11043   | Text -> (* an unnamed field in an element *)
11044       "data"
11045   | rng ->
11046       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11047
11048 (* At the moment this function only generates OCaml types.  However we
11049  * should parameterize it later so it can generate types/structs in a
11050  * variety of languages.
11051  *)
11052 let generate_types xs =
11053   (* A simple type is one that can be printed out directly, eg.
11054    * "string option".  A complex type is one which has a name and has
11055    * to be defined via another toplevel definition, eg. a struct.
11056    *
11057    * generate_type generates code for either simple or complex types.
11058    * In the simple case, it returns the string ("string option").  In
11059    * the complex case, it returns the name ("mountpoint").  In the
11060    * complex case it has to print out the definition before returning,
11061    * so it should only be called when we are at the beginning of a
11062    * new line (BOL context).
11063    *)
11064   let rec generate_type = function
11065     | Text ->                                (* string *)
11066         "string", true
11067     | Choice values ->                        (* [`val1|`val2|...] *)
11068         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11069     | ZeroOrMore rng ->                        (* <rng> list *)
11070         let t, is_simple = generate_type rng in
11071         t ^ " list (* 0 or more *)", is_simple
11072     | OneOrMore rng ->                        (* <rng> list *)
11073         let t, is_simple = generate_type rng in
11074         t ^ " list (* 1 or more *)", is_simple
11075                                         (* virt-inspector hack: bool *)
11076     | Optional (Attribute (name, [Value "1"])) ->
11077         "bool", true
11078     | Optional rng ->                        (* <rng> list *)
11079         let t, is_simple = generate_type rng in
11080         t ^ " option", is_simple
11081                                         (* type name = { fields ... } *)
11082     | Element (name, fields) when is_attrs_interleave fields ->
11083         generate_type_struct name (get_attrs_interleave fields)
11084     | Element (name, [field])                (* type name = field *)
11085     | Attribute (name, [field]) ->
11086         let t, is_simple = generate_type field in
11087         if is_simple then (t, true)
11088         else (
11089           pr "type %s = %s\n" name t;
11090           name, false
11091         )
11092     | Element (name, fields) ->              (* type name = { fields ... } *)
11093         generate_type_struct name fields
11094     | rng ->
11095         failwithf "generate_type failed at: %s" (string_of_rng rng)
11096
11097   and is_attrs_interleave = function
11098     | [Interleave _] -> true
11099     | Attribute _ :: fields -> is_attrs_interleave fields
11100     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11101     | _ -> false
11102
11103   and get_attrs_interleave = function
11104     | [Interleave fields] -> fields
11105     | ((Attribute _) as field) :: fields
11106     | ((Optional (Attribute _)) as field) :: fields ->
11107         field :: get_attrs_interleave fields
11108     | _ -> assert false
11109
11110   and generate_types xs =
11111     List.iter (fun x -> ignore (generate_type x)) xs
11112
11113   and generate_type_struct name fields =
11114     (* Calculate the types of the fields first.  We have to do this
11115      * before printing anything so we are still in BOL context.
11116      *)
11117     let types = List.map fst (List.map generate_type fields) in
11118
11119     (* Special case of a struct containing just a string and another
11120      * field.  Turn it into an assoc list.
11121      *)
11122     match types with
11123     | ["string"; other] ->
11124         let fname1, fname2 =
11125           match fields with
11126           | [f1; f2] -> name_of_field f1, name_of_field f2
11127           | _ -> assert false in
11128         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11129         name, false
11130
11131     | types ->
11132         pr "type %s = {\n" name;
11133         List.iter (
11134           fun (field, ftype) ->
11135             let fname = name_of_field field in
11136             pr "  %s_%s : %s;\n" name fname ftype
11137         ) (List.combine fields types);
11138         pr "}\n";
11139         (* Return the name of this type, and
11140          * false because it's not a simple type.
11141          *)
11142         name, false
11143   in
11144
11145   generate_types xs
11146
11147 let generate_parsers xs =
11148   (* As for generate_type above, generate_parser makes a parser for
11149    * some type, and returns the name of the parser it has generated.
11150    * Because it (may) need to print something, it should always be
11151    * called in BOL context.
11152    *)
11153   let rec generate_parser = function
11154     | Text ->                                (* string *)
11155         "string_child_or_empty"
11156     | Choice values ->                        (* [`val1|`val2|...] *)
11157         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11158           (String.concat "|"
11159              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11160     | ZeroOrMore rng ->                        (* <rng> list *)
11161         let pa = generate_parser rng in
11162         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11163     | OneOrMore rng ->                        (* <rng> list *)
11164         let pa = generate_parser rng in
11165         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11166                                         (* virt-inspector hack: bool *)
11167     | Optional (Attribute (name, [Value "1"])) ->
11168         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11169     | Optional rng ->                        (* <rng> list *)
11170         let pa = generate_parser rng in
11171         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11172                                         (* type name = { fields ... } *)
11173     | Element (name, fields) when is_attrs_interleave fields ->
11174         generate_parser_struct name (get_attrs_interleave fields)
11175     | Element (name, [field]) ->        (* type name = field *)
11176         let pa = generate_parser field in
11177         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11178         pr "let %s =\n" parser_name;
11179         pr "  %s\n" pa;
11180         pr "let parse_%s = %s\n" name parser_name;
11181         parser_name
11182     | Attribute (name, [field]) ->
11183         let pa = generate_parser field in
11184         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11185         pr "let %s =\n" parser_name;
11186         pr "  %s\n" pa;
11187         pr "let parse_%s = %s\n" name parser_name;
11188         parser_name
11189     | Element (name, fields) ->              (* type name = { fields ... } *)
11190         generate_parser_struct name ([], fields)
11191     | rng ->
11192         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11193
11194   and is_attrs_interleave = function
11195     | [Interleave _] -> true
11196     | Attribute _ :: fields -> is_attrs_interleave fields
11197     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11198     | _ -> false
11199
11200   and get_attrs_interleave = function
11201     | [Interleave fields] -> [], fields
11202     | ((Attribute _) as field) :: fields
11203     | ((Optional (Attribute _)) as field) :: fields ->
11204         let attrs, interleaves = get_attrs_interleave fields in
11205         (field :: attrs), interleaves
11206     | _ -> assert false
11207
11208   and generate_parsers xs =
11209     List.iter (fun x -> ignore (generate_parser x)) xs
11210
11211   and generate_parser_struct name (attrs, interleaves) =
11212     (* Generate parsers for the fields first.  We have to do this
11213      * before printing anything so we are still in BOL context.
11214      *)
11215     let fields = attrs @ interleaves in
11216     let pas = List.map generate_parser fields in
11217
11218     (* Generate an intermediate tuple from all the fields first.
11219      * If the type is just a string + another field, then we will
11220      * return this directly, otherwise it is turned into a record.
11221      *
11222      * RELAX NG note: This code treats <interleave> and plain lists of
11223      * fields the same.  In other words, it doesn't bother enforcing
11224      * any ordering of fields in the XML.
11225      *)
11226     pr "let parse_%s x =\n" name;
11227     pr "  let t = (\n    ";
11228     let comma = ref false in
11229     List.iter (
11230       fun x ->
11231         if !comma then pr ",\n    ";
11232         comma := true;
11233         match x with
11234         | Optional (Attribute (fname, [field])), pa ->
11235             pr "%s x" pa
11236         | Optional (Element (fname, [field])), pa ->
11237             pr "%s (optional_child %S x)" pa fname
11238         | Attribute (fname, [Text]), _ ->
11239             pr "attribute %S x" fname
11240         | (ZeroOrMore _ | OneOrMore _), pa ->
11241             pr "%s x" pa
11242         | Text, pa ->
11243             pr "%s x" pa
11244         | (field, pa) ->
11245             let fname = name_of_field field in
11246             pr "%s (child %S x)" pa fname
11247     ) (List.combine fields pas);
11248     pr "\n  ) in\n";
11249
11250     (match fields with
11251      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11252          pr "  t\n"
11253
11254      | _ ->
11255          pr "  (Obj.magic t : %s)\n" name
11256 (*
11257          List.iter (
11258            function
11259            | (Optional (Attribute (fname, [field])), pa) ->
11260                pr "  %s_%s =\n" name fname;
11261                pr "    %s x;\n" pa
11262            | (Optional (Element (fname, [field])), pa) ->
11263                pr "  %s_%s =\n" name fname;
11264                pr "    (let x = optional_child %S x in\n" fname;
11265                pr "     %s x);\n" pa
11266            | (field, pa) ->
11267                let fname = name_of_field field in
11268                pr "  %s_%s =\n" name fname;
11269                pr "    (let x = child %S x in\n" fname;
11270                pr "     %s x);\n" pa
11271          ) (List.combine fields pas);
11272          pr "}\n"
11273 *)
11274     );
11275     sprintf "parse_%s" name
11276   in
11277
11278   generate_parsers xs
11279
11280 (* Generate ocaml/guestfs_inspector.mli. *)
11281 let generate_ocaml_inspector_mli () =
11282   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11283
11284   pr "\
11285 (** This is an OCaml language binding to the external [virt-inspector]
11286     program.
11287
11288     For more information, please read the man page [virt-inspector(1)].
11289 *)
11290
11291 ";
11292
11293   generate_types grammar;
11294   pr "(** The nested information returned from the {!inspect} function. *)\n";
11295   pr "\n";
11296
11297   pr "\
11298 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11299 (** To inspect a libvirt domain called [name], pass a singleton
11300     list: [inspect [name]].  When using libvirt only, you may
11301     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11302
11303     To inspect a disk image or images, pass a list of the filenames
11304     of the disk images: [inspect filenames]
11305
11306     This function inspects the given guest or disk images and
11307     returns a list of operating system(s) found and a large amount
11308     of information about them.  In the vast majority of cases,
11309     a virtual machine only contains a single operating system.
11310
11311     If the optional [~xml] parameter is given, then this function
11312     skips running the external virt-inspector program and just
11313     parses the given XML directly (which is expected to be XML
11314     produced from a previous run of virt-inspector).  The list of
11315     names and connect URI are ignored in this case.
11316
11317     This function can throw a wide variety of exceptions, for example
11318     if the external virt-inspector program cannot be found, or if
11319     it doesn't generate valid XML.
11320 *)
11321 "
11322
11323 (* Generate ocaml/guestfs_inspector.ml. *)
11324 let generate_ocaml_inspector_ml () =
11325   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11326
11327   pr "open Unix\n";
11328   pr "\n";
11329
11330   generate_types grammar;
11331   pr "\n";
11332
11333   pr "\
11334 (* Misc functions which are used by the parser code below. *)
11335 let first_child = function
11336   | Xml.Element (_, _, c::_) -> c
11337   | Xml.Element (name, _, []) ->
11338       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11339   | Xml.PCData str ->
11340       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11341
11342 let string_child_or_empty = function
11343   | Xml.Element (_, _, [Xml.PCData s]) -> s
11344   | Xml.Element (_, _, []) -> \"\"
11345   | Xml.Element (x, _, _) ->
11346       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11347                 x ^ \" instead\")
11348   | Xml.PCData str ->
11349       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11350
11351 let optional_child name xml =
11352   let children = Xml.children xml in
11353   try
11354     Some (List.find (function
11355                      | Xml.Element (n, _, _) when n = name -> true
11356                      | _ -> false) children)
11357   with
11358     Not_found -> None
11359
11360 let child name xml =
11361   match optional_child name xml with
11362   | Some c -> c
11363   | None ->
11364       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11365
11366 let attribute name xml =
11367   try Xml.attrib xml name
11368   with Xml.No_attribute _ ->
11369     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11370
11371 ";
11372
11373   generate_parsers grammar;
11374   pr "\n";
11375
11376   pr "\
11377 (* Run external virt-inspector, then use parser to parse the XML. *)
11378 let inspect ?connect ?xml names =
11379   let xml =
11380     match xml with
11381     | None ->
11382         if names = [] then invalid_arg \"inspect: no names given\";
11383         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11384           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11385           names in
11386         let cmd = List.map Filename.quote cmd in
11387         let cmd = String.concat \" \" cmd in
11388         let chan = open_process_in cmd in
11389         let xml = Xml.parse_in chan in
11390         (match close_process_in chan with
11391          | WEXITED 0 -> ()
11392          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11393          | WSIGNALED i | WSTOPPED i ->
11394              failwith (\"external virt-inspector command died or stopped on sig \" ^
11395                        string_of_int i)
11396         );
11397         xml
11398     | Some doc ->
11399         Xml.parse_string doc in
11400   parse_operatingsystems xml
11401 "
11402
11403 (* This is used to generate the src/MAX_PROC_NR file which
11404  * contains the maximum procedure number, a surrogate for the
11405  * ABI version number.  See src/Makefile.am for the details.
11406  *)
11407 and generate_max_proc_nr () =
11408   let proc_nrs = List.map (
11409     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11410   ) daemon_functions in
11411
11412   let max_proc_nr = List.fold_left max 0 proc_nrs in
11413
11414   pr "%d\n" max_proc_nr
11415
11416 let output_to filename k =
11417   let filename_new = filename ^ ".new" in
11418   chan := open_out filename_new;
11419   k ();
11420   close_out !chan;
11421   chan := Pervasives.stdout;
11422
11423   (* Is the new file different from the current file? *)
11424   if Sys.file_exists filename && files_equal filename filename_new then
11425     unlink filename_new                 (* same, so skip it *)
11426   else (
11427     (* different, overwrite old one *)
11428     (try chmod filename 0o644 with Unix_error _ -> ());
11429     rename filename_new filename;
11430     chmod filename 0o444;
11431     printf "written %s\n%!" filename;
11432   )
11433
11434 let perror msg = function
11435   | Unix_error (err, _, _) ->
11436       eprintf "%s: %s\n" msg (error_message err)
11437   | exn ->
11438       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11439
11440 (* Main program. *)
11441 let () =
11442   let lock_fd =
11443     try openfile "HACKING" [O_RDWR] 0
11444     with
11445     | Unix_error (ENOENT, _, _) ->
11446         eprintf "\
11447 You are probably running this from the wrong directory.
11448 Run it from the top source directory using the command
11449   src/generator.ml
11450 ";
11451         exit 1
11452     | exn ->
11453         perror "open: HACKING" exn;
11454         exit 1 in
11455
11456   (* Acquire a lock so parallel builds won't try to run the generator
11457    * twice at the same time.  Subsequent builds will wait for the first
11458    * one to finish.  Note the lock is released implicitly when the
11459    * program exits.
11460    *)
11461   (try lockf lock_fd F_LOCK 1
11462    with exn ->
11463      perror "lock: HACKING" exn;
11464      exit 1);
11465
11466   check_functions ();
11467
11468   output_to "src/guestfs_protocol.x" generate_xdr;
11469   output_to "src/guestfs-structs.h" generate_structs_h;
11470   output_to "src/guestfs-actions.h" generate_actions_h;
11471   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11472   output_to "src/guestfs-actions.c" generate_client_actions;
11473   output_to "src/guestfs-bindtests.c" generate_bindtests;
11474   output_to "src/guestfs-structs.pod" generate_structs_pod;
11475   output_to "src/guestfs-actions.pod" generate_actions_pod;
11476   output_to "src/guestfs-availability.pod" generate_availability_pod;
11477   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11478   output_to "src/libguestfs.syms" generate_linker_script;
11479   output_to "daemon/actions.h" generate_daemon_actions_h;
11480   output_to "daemon/stubs.c" generate_daemon_actions;
11481   output_to "daemon/names.c" generate_daemon_names;
11482   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11483   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11484   output_to "capitests/tests.c" generate_tests;
11485   output_to "fish/cmds.c" generate_fish_cmds;
11486   output_to "fish/completion.c" generate_fish_completion;
11487   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11488   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11489   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11490   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11491   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11492   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11493   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11494   output_to "perl/Guestfs.xs" generate_perl_xs;
11495   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11496   output_to "perl/bindtests.pl" generate_perl_bindtests;
11497   output_to "python/guestfs-py.c" generate_python_c;
11498   output_to "python/guestfs.py" generate_python_py;
11499   output_to "python/bindtests.py" generate_python_bindtests;
11500   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11501   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11502   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11503
11504   List.iter (
11505     fun (typ, jtyp) ->
11506       let cols = cols_of_struct typ in
11507       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11508       output_to filename (generate_java_struct jtyp cols);
11509   ) java_structs;
11510
11511   output_to "java/Makefile.inc" generate_java_makefile_inc;
11512   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11513   output_to "java/Bindtests.java" generate_java_bindtests;
11514   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11515   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11516   output_to "csharp/Libguestfs.cs" generate_csharp;
11517
11518   (* Always generate this file last, and unconditionally.  It's used
11519    * by the Makefile to know when we must re-run the generator.
11520    *)
11521   let chan = open_out "src/stamp-generator" in
11522   fprintf chan "1\n";
11523   close_out chan;
11524
11525   printf "generated %d lines of code\n" !lines