New API: vgscan
[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   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2030
2031   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2032    [],
2033    "pack directory into tarfile",
2034    "\
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2037
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_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_zero_device>, 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   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mkfifo"; "0o777"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984    "make FIFO (named pipe)",
2985    "\
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>.  It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2989
2990   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994    "make block device node",
2995    "\
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
2999
3000   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004    "make char device node",
3005    "\
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011    [], (* XXX umask is one of those stateful things that we should
3012         * reset between each test.
3013         *)
3014    "set file mode creation mask (umask)",
3015    "\
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3018
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3023
3024 The default umask is C<022>.  This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3027
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3029
3030 This call returns the previous umask.");
3031
3032   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3033    [],
3034    "read directories entries",
3035    "\
3036 This returns the list of directory entries in directory C<dir>.
3037
3038 All entries in the directory are returned, including C<.> and
3039 C<..>.  The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3041
3042 Also this call returns basic file type information about each
3043 file.  The C<ftyp> field will contain one of the following characters:
3044
3045 =over 4
3046
3047 =item 'b'
3048
3049 Block special
3050
3051 =item 'c'
3052
3053 Char special
3054
3055 =item 'd'
3056
3057 Directory
3058
3059 =item 'f'
3060
3061 FIFO (named pipe)
3062
3063 =item 'l'
3064
3065 Symbolic link
3066
3067 =item 'r'
3068
3069 Regular file
3070
3071 =item 's'
3072
3073 Socket
3074
3075 =item 'u'
3076
3077 Unknown file type
3078
3079 =item '?'
3080
3081 The L<readdir(3)> returned a C<d_type> field with an
3082 unexpected value
3083
3084 =back
3085
3086 This function is primarily intended for use by programs.  To
3087 get a simple list of names, use C<guestfs_ls>.  To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3089
3090   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3091    [],
3092    "create partitions on a block device",
3093    "\
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3099
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3102
3103   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3104    [],
3105    "determine file type inside a compressed file",
3106    "\
3107 This command runs C<file> after first decompressing C<path>
3108 using C<method>.
3109
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3111
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3114
3115   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3116    [],
3117    "list extended attributes of a file or directory",
3118    "\
3119 This call lists the extended attributes of the file or directory
3120 C<path>.
3121
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3124
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3126
3127   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3128    [],
3129    "list extended attributes of a file or directory",
3130    "\
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3134
3135   ("setxattr", (RErr, [String "xattr";
3136                        String "val"; Int "vallen"; (* will be BufferIn *)
3137                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3138    [],
3139    "set extended attribute of a file or directory",
3140    "\
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3144
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3146
3147   ("lsetxattr", (RErr, [String "xattr";
3148                         String "val"; Int "vallen"; (* will be BufferIn *)
3149                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3150    [],
3151    "set extended attribute of a file or directory",
3152    "\
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3156
3157   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3158    [],
3159    "remove extended attribute of a file or directory",
3160    "\
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3163
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3165
3166   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3167    [],
3168    "remove extended attribute of a file or directory",
3169    "\
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3173
3174   ("mountpoints", (RHashtable "mps", []), 147, [],
3175    [],
3176    "show mountpoints",
3177    "\
3178 This call is similar to C<guestfs_mounts>.  That call returns
3179 a list of devices.  This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3181
3182   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183    (* This is a special case: while you would expect a parameter
3184     * of type "Pathname", that doesn't work, because it implies
3185     * NEED_ROOT in the generated calling code in stubs.c, and
3186     * this function cannot use NEED_ROOT.
3187     *)
3188    [],
3189    "create a mountpoint",
3190    "\
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3194
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3198
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that.  You can unpack this as follows
3202 in guestfish:
3203
3204  add-ro Fedora-11-i686-Live.iso
3205  run
3206  mkmountpoint /cd
3207  mkmountpoint /squash
3208  mkmountpoint /ext3
3209  mount /dev/sda /cd
3210  mount-loop /cd/LiveOS/squashfs.img /squash
3211  mount-loop /squash/LiveOS/ext3fs.img /ext3
3212
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3214
3215   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3216    [],
3217    "remove a mountpoint",
3218    "\
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3221 for full details.");
3222
3223   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputBuffer (
3225       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3226    "read a file",
3227    "\
3228 This calls returns the contents of the file C<path> as a
3229 buffer.
3230
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3235
3236   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239     InitISOFS, Always, TestOutputList (
3240       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241    "return lines matching a pattern",
3242    "\
3243 This calls the external C<grep> program and returns the
3244 matching lines.");
3245
3246   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249    "return lines matching a pattern",
3250    "\
3251 This calls the external C<egrep> program and returns the
3252 matching lines.");
3253
3254   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255    [InitISOFS, Always, TestOutputList (
3256       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257    "return lines matching a pattern",
3258    "\
3259 This calls the external C<fgrep> program and returns the
3260 matching lines.");
3261
3262   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263    [InitISOFS, Always, TestOutputList (
3264       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265    "return lines matching a pattern",
3266    "\
3267 This calls the external C<grep -i> program and returns the
3268 matching lines.");
3269
3270   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271    [InitISOFS, Always, TestOutputList (
3272       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<egrep -i> program and returns the
3276 matching lines.");
3277
3278   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<fgrep -i> program and returns the
3284 matching lines.");
3285
3286   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<zgrep> program and returns the
3292 matching lines.");
3293
3294   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<zegrep> program and returns the
3300 matching lines.");
3301
3302   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<zfgrep> program and returns the
3308 matching lines.");
3309
3310   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<zgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zegrep -i> program and returns the
3324 matching lines.");
3325
3326   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zfgrep -i> program and returns the
3332 matching lines.");
3333
3334   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335    [InitISOFS, Always, TestOutput (
3336       [["realpath"; "/../directory"]], "/directory")],
3337    "canonicalized absolute pathname",
3338    "\
3339 Return the canonicalized absolute pathname of C<path>.  The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3341
3342   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343    [InitBasicFS, Always, TestOutputStruct (
3344       [["touch"; "/a"];
3345        ["ln"; "/a"; "/b"];
3346        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347    "create a hard link",
3348    "\
3349 This command creates a hard link using the C<ln> command.");
3350
3351   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352    [InitBasicFS, Always, TestOutputStruct (
3353       [["touch"; "/a"];
3354        ["touch"; "/b"];
3355        ["ln_f"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3361
3362   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln_s"; "a"; "/b"];
3366        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367    "create a symbolic link",
3368    "\
3369 This command creates a symbolic link using the C<ln -s> command.");
3370
3371   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372    [InitBasicFS, Always, TestOutput (
3373       [["mkdir_p"; "/a/b"];
3374        ["touch"; "/a/b/c"];
3375        ["ln_sf"; "../d"; "/a/b/c"];
3376        ["readlink"; "/a/b/c"]], "../d")],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383    [] (* XXX tested above *),
3384    "read the target of a symbolic link",
3385    "\
3386 This command reads the target of a symbolic link.");
3387
3388   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389    [InitBasicFS, Always, TestOutputStruct (
3390       [["fallocate"; "/a"; "1000000"];
3391        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392    "preallocate a file in the guest filesystem",
3393    "\
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes.  If the file exists already, it
3396 is overwritten.
3397
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3401
3402   ("swapon_device", (RErr, [Device "device"]), 170, [],
3403    [InitPartition, Always, TestRun (
3404       [["mkswap"; "/dev/sda1"];
3405        ["swapon_device"; "/dev/sda1"];
3406        ["swapoff_device"; "/dev/sda1"]])],
3407    "enable swap on device",
3408    "\
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>.  The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3413
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing.  They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash.  You also risk leaking
3418 information about the host to the guest this way.  Instead,
3419 attach a new host device to the guest and swap on that.");
3420
3421   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422    [], (* XXX tested by swapon_device *)
3423    "disable swap on device",
3424    "\
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3428
3429   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430    [InitBasicFS, Always, TestRun (
3431       [["fallocate"; "/swap"; "8388608"];
3432        ["mkswap_file"; "/swap"];
3433        ["swapon_file"; "/swap"];
3434        ["swapoff_file"; "/swap"]])],
3435    "enable swap on file",
3436    "\
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3439
3440   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441    [], (* XXX tested by swapon_file *)
3442    "disable swap on file",
3443    "\
3444 This command disables the libguestfs appliance swap on file.");
3445
3446   ("swapon_label", (RErr, [String "label"]), 174, [],
3447    [InitEmpty, Always, TestRun (
3448       [["part_disk"; "/dev/sdb"; "mbr"];
3449        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450        ["swapon_label"; "swapit"];
3451        ["swapoff_label"; "swapit"];
3452        ["zero"; "/dev/sdb"];
3453        ["blockdev_rereadpt"; "/dev/sdb"]])],
3454    "enable swap on labeled swap partition",
3455    "\
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3458
3459   ("swapoff_label", (RErr, [String "label"]), 175, [],
3460    [], (* XXX tested by swapon_label *)
3461    "disable swap on labeled swap partition",
3462    "\
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3465
3466   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467    (let uuid = uuidgen () in
3468     [InitEmpty, Always, TestRun (
3469        [["mkswap_U"; uuid; "/dev/sdb"];
3470         ["swapon_uuid"; uuid];
3471         ["swapoff_uuid"; uuid]])]),
3472    "enable swap on swap partition by UUID",
3473    "\
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3476
3477   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478    [], (* XXX tested by swapon_uuid *)
3479    "disable swap on swap partition by UUID",
3480    "\
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3483
3484   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485    [InitBasicFS, Always, TestRun (
3486       [["fallocate"; "/swap"; "8388608"];
3487        ["mkswap_file"; "/swap"]])],
3488    "create a swap file",
3489    "\
3490 Create a swap file.
3491
3492 This command just writes a swap file signature to an existing
3493 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3494
3495   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496    [InitISOFS, Always, TestRun (
3497       [["inotify_init"; "0"]])],
3498    "create an inotify handle",
3499    "\
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3503
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used.  For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3513
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list.  See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3519
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>).  If you don't
3524 read the events out often enough then you risk the internal
3525 queue overflowing.
3526
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>.  This also removes any
3529 watches automatically.
3530
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs.  Note that there is one global inotify handle
3534 per libguestfs instance.");
3535
3536   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537    [InitBasicFS, Always, TestOutputList (
3538       [["inotify_init"; "0"];
3539        ["inotify_add_watch"; "/"; "1073741823"];
3540        ["touch"; "/a"];
3541        ["touch"; "/b"];
3542        ["inotify_files"]], ["a"; "b"])],
3543    "add an inotify watch",
3544    "\
3545 Watch C<path> for the events listed in C<mask>.
3546
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3550
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3554
3555   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3556    [],
3557    "remove an inotify watch",
3558    "\
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3561
3562   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3563    [],
3564    "return list of inotify events",
3565    "\
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3568
3569 If no events have happened, this returns an empty list.
3570
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list.  The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3576
3577   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3578    [],
3579    "return list of watched files that had events",
3580    "\
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched.  The returned pathnames are sorted and deduplicated.");
3584
3585   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3586    [],
3587    "close the inotify handle",
3588    "\
3589 This closes the inotify handle which was previously
3590 opened by inotify_init.  It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3592
3593   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3594    [],
3595    "set SELinux security context",
3596    "\
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3599
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3601
3602   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3603    [],
3604    "get SELinux security context",
3605    "\
3606 This gets the SELinux security context of the daemon.
3607
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3610
3611   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612    [InitEmpty, Always, TestOutput (
3613       [["part_disk"; "/dev/sda"; "mbr"];
3614        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615        ["mount_options"; ""; "/dev/sda1"; "/"];
3616        ["write_file"; "/new"; "new file contents"; "0"];
3617        ["cat"; "/new"]], "new file contents")],
3618    "make a filesystem with block size",
3619    "\
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem.  Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3624
3625   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626    [InitEmpty, Always, TestOutput (
3627       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628        ["mke2journal"; "4096"; "/dev/sda1"];
3629        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda2"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make ext2/3/4 external journal",
3634    "\
3635 This creates an ext2 external journal on C<device>.  It is equivalent
3636 to the command:
3637
3638  mke2fs -O journal_dev -b blocksize device");
3639
3640   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
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 with label",
3649    "\
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3651
3652   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653    (let uuid = uuidgen () in
3654     [InitEmpty, Always, TestOutput (
3655        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658         ["mount_options"; ""; "/dev/sda2"; "/"];
3659         ["write_file"; "/new"; "new file contents"; "0"];
3660         ["cat"; "/new"]], "new file contents")]),
3661    "make ext2/3/4 external journal with UUID",
3662    "\
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3664
3665   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3666    [],
3667    "make ext2/3/4 filesystem with external journal",
3668    "\
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>.  It is equivalent
3671 to the command:
3672
3673  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3674
3675 See also C<guestfs_mke2journal>.");
3676
3677   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3678    [],
3679    "make ext2/3/4 filesystem with external journal",
3680    "\
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3683
3684 See also C<guestfs_mke2journal_L>.");
3685
3686   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3687    [],
3688    "make ext2/3/4 filesystem with external journal",
3689    "\
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3692
3693 See also C<guestfs_mke2journal_U>.");
3694
3695   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697    "load a kernel module",
3698    "\
3699 This loads a kernel module in the appliance.
3700
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3703
3704   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705    [InitNone, Always, TestOutput (
3706       [["echo_daemon"; "This is a test"]], "This is a test"
3707     )],
3708    "echo arguments back to the client",
3709    "\
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3712
3713 You can use this command to test the connection through to the daemon.
3714
3715 See also C<guestfs_ping_daemon>.");
3716
3717   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718    [], (* There is a regression test for this. *)
3719    "find all files and directories, returning NUL-separated list",
3720    "\
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3724
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3727
3728 =over 4
3729
3730 =item *
3731
3732 The resulting list is written to an external file.
3733
3734 =item *
3735
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3738
3739 =item *
3740
3741 This command is not limited in the number of names that it
3742 can return.
3743
3744 =item *
3745
3746 The result list is not sorted.
3747
3748 =back");
3749
3750   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751    [InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755     InitISOFS, Always, TestOutput (
3756       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757     InitISOFS, Always, TestLastFail (
3758       [["case_sensitive_path"; "/Known-1/"]]);
3759     InitBasicFS, Always, TestOutput (
3760       [["mkdir"; "/a"];
3761        ["mkdir"; "/a/bbb"];
3762        ["touch"; "/a/bbb/c"];
3763        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3764     InitBasicFS, Always, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestLastFail (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774    "return true path on case-insensitive filesystem",
3775    "\
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive.  The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3780
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3785
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created.  In Windows itself this would not be
3790 a problem.
3791
3792 Bug or feature?  You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3794
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3797
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3802
3803 I<Note>:
3804 This function does not handle drive names, backslashes etc.
3805
3806 See also C<guestfs_realpath>.");
3807
3808   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809    [InitBasicFS, Always, TestOutput (
3810       [["vfs_type"; "/dev/sda1"]], "ext2")],
3811    "get the Linux VFS type corresponding to a mounted device",
3812    "\
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3815
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3819
3820   ("truncate", (RErr, [Pathname "path"]), 199, [],
3821    [InitBasicFS, Always, TestOutputStruct (
3822       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823        ["truncate"; "/test"];
3824        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825    "truncate a file to zero size",
3826    "\
3827 This command truncates C<path> to a zero-length file.  The
3828 file must exist already.");
3829
3830   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["touch"; "/test"];
3833        ["truncate_size"; "/test"; "1000"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835    "truncate a file to a particular size",
3836    "\
3837 This command truncates C<path> to size C<size> bytes.  The file
3838 must exist already.  If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3840
3841   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842    [InitBasicFS, Always, TestOutputStruct (
3843       [["touch"; "/test"];
3844        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846    "set timestamp of a file with nanosecond precision",
3847    "\
3848 This command sets the timestamps of a file with nanosecond
3849 precision.
3850
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3853
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3856
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time.  (The
3859 C<*secs> field is ignored in this case).
3860
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged.  (The
3863 C<*secs> field is ignored in this case).");
3864
3865   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866    [InitBasicFS, Always, TestOutputStruct (
3867       [["mkdir_mode"; "/test"; "0o111"];
3868        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869    "create a directory with a particular mode",
3870    "\
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3873
3874   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3875    [], (* XXX *)
3876    "change file owner and group",
3877    "\
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3881
3882 Only numeric uid and gid are supported.  If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3885
3886   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3887    [], (* XXX *)
3888    "lstat on multiple files",
3889    "\
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3893
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list.  If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3897 is set to C<-1>.
3898
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes.  Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail.  The caller must split up such requests
3905 into smaller groups of names.");
3906
3907   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3908    [], (* XXX *)
3909    "lgetxattr on multiple files",
3910    "\
3911 This call allows you to get the extended attributes
3912 of 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 flat list of xattr structs which must be
3916 interpreted sequentially.  The first xattr struct always has a zero-length
3917 C<attrname>.  C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">).  Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3934    [], (* XXX *)
3935    "readlink on multiple files",
3936    "\
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list.  Each string is the
3943 value of the symbol link.
3944
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3951
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960    [InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/known-4"; "1"; "3"]], "\n");
3962     InitISOFS, Always, TestOutputBuffer (
3963       [["pread"; "/empty"; "0"; "100"]], "")],
3964    "read part of a file",
3965    "\
3966 This command lets you read part of a file.  It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3968
3969 This may read fewer bytes than requested.  For further details
3970 see the L<pread(2)> system call.");
3971
3972   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973    [InitEmpty, Always, TestRun (
3974       [["part_init"; "/dev/sda"; "gpt"]])],
3975    "create an empty partition table",
3976    "\
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below.  Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3980
3981 Initially there are no partitions.  Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3983
3984 Possible values for C<parttype> are:
3985
3986 =over 4
3987
3988 =item B<efi> | B<gpt>
3989
3990 Intel EFI / GPT partition table.
3991
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X.  It also has limited backwards
3994 compatibility with the C<mbr> format.
3995
3996 =item B<mbr> | B<msdos>
3997
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows.  This partition type will B<only> work
4000 for device sizes up to 2 TB.  For large disks we recommend
4001 using C<gpt>.
4002
4003 =back
4004
4005 Other partition table types that may work but are not
4006 supported include:
4007
4008 =over 4
4009
4010 =item B<aix>
4011
4012 AIX disk labels.
4013
4014 =item B<amiga> | B<rdb>
4015
4016 Amiga \"Rigid Disk Block\" format.
4017
4018 =item B<bsd>
4019
4020 BSD disk labels.
4021
4022 =item B<dasd>
4023
4024 DASD, used on IBM mainframes.
4025
4026 =item B<dvh>
4027
4028 MIPS/SGI volumes.
4029
4030 =item B<mac>
4031
4032 Old Mac partition format.  Modern Macs use C<gpt>.
4033
4034 =item B<pc98>
4035
4036 NEC PC-98 format, common in Japan apparently.
4037
4038 =item B<sun>
4039
4040 Sun disk labels.
4041
4042 =back");
4043
4044   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045    [InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "mbr"];
4047        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048     InitEmpty, Always, TestRun (
4049       [["part_init"; "/dev/sda"; "gpt"];
4050        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052     InitEmpty, Always, TestRun (
4053       [["part_init"; "/dev/sda"; "mbr"];
4054        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058    "add a partition to the device",
4059    "\
4060 This command adds a partition to C<device>.  If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4062
4063 The C<prlogex> parameter is the type of partition.  Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4066 types.
4067
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>.  C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4071
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4074
4075   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076    [InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "mbr"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_disk"; "/dev/sda"; "gpt"]])],
4080    "partition whole disk with a single primary partition",
4081    "\
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4085
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4088
4089   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090    [InitEmpty, Always, TestRun (
4091       [["part_disk"; "/dev/sda"; "mbr"];
4092        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093    "make a partition bootable",
4094    "\
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>.  Note that partitions are numbered from 1.
4097
4098 The bootable flag is used by some PC BIOSes to determine which
4099 partition to boot from.  It is by no means universally recognized,
4100 and in any case if your operating system installed a boot
4101 sector on the device itself, then that takes precedence.");
4102
4103   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4104    [InitEmpty, Always, TestRun (
4105       [["part_disk"; "/dev/sda"; "gpt"];
4106        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4107    "set partition name",
4108    "\
4109 This sets the partition name on partition numbered C<partnum> on
4110 device C<device>.  Note that partitions are numbered from 1.
4111
4112 The partition name can only be set on certain types of partition
4113 table.  This works on C<gpt> but not on C<mbr> partitions.");
4114
4115   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4116    [], (* XXX Add a regression test for this. *)
4117    "list partitions on a device",
4118    "\
4119 This command parses the partition table on C<device> and
4120 returns the list of partitions found.
4121
4122 The fields in the returned structure are:
4123
4124 =over 4
4125
4126 =item B<part_num>
4127
4128 Partition number, counting from 1.
4129
4130 =item B<part_start>
4131
4132 Start of the partition I<in bytes>.  To get sectors you have to
4133 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4134
4135 =item B<part_end>
4136
4137 End of the partition in bytes.
4138
4139 =item B<part_size>
4140
4141 Size of the partition in bytes.
4142
4143 =back");
4144
4145   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4146    [InitEmpty, Always, TestOutput (
4147       [["part_disk"; "/dev/sda"; "gpt"];
4148        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4149    "get the partition table type",
4150    "\
4151 This command examines the partition table on C<device> and
4152 returns the partition table type (format) being used.
4153
4154 Common return values include: C<msdos> (a DOS/Windows style MBR
4155 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4156 values are possible, although unusual.  See C<guestfs_part_init>
4157 for a full list.");
4158
4159   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4160    [InitBasicFS, Always, TestOutputBuffer (
4161       [["fill"; "0x63"; "10"; "/test"];
4162        ["read_file"; "/test"]], "cccccccccc")],
4163    "fill a file with octets",
4164    "\
4165 This command creates a new file called C<path>.  The initial
4166 content of the file is C<len> octets of C<c>, where C<c>
4167 must be a number in the range C<[0..255]>.
4168
4169 To fill a file with zero bytes (sparsely), it is
4170 much more efficient to use C<guestfs_truncate_size>.");
4171
4172   ("available", (RErr, [StringList "groups"]), 216, [],
4173    [InitNone, Always, TestRun [["available"; ""]]],
4174    "test availability of some parts of the API",
4175    "\
4176 This command is used to check the availability of some
4177 groups of functionality in the appliance, which not all builds of
4178 the libguestfs appliance will be able to provide.
4179
4180 The libguestfs groups, and the functions that those
4181 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4182
4183 The argument C<groups> is a list of group names, eg:
4184 C<[\"inotify\", \"augeas\"]> would check for the availability of
4185 the Linux inotify functions and Augeas (configuration file
4186 editing) functions.
4187
4188 The command returns no error if I<all> requested groups are available.
4189
4190 It fails with an error if one or more of the requested
4191 groups is unavailable in the appliance.
4192
4193 If an unknown group name is included in the
4194 list of groups then an error is always returned.
4195
4196 I<Notes:>
4197
4198 =over 4
4199
4200 =item *
4201
4202 You must call C<guestfs_launch> before calling this function.
4203
4204 The reason is because we don't know what groups are
4205 supported by the appliance/daemon until it is running and can
4206 be queried.
4207
4208 =item *
4209
4210 If a group of functions is available, this does not necessarily
4211 mean that they will work.  You still have to check for errors
4212 when calling individual API functions even if they are
4213 available.
4214
4215 =item *
4216
4217 It is usually the job of distro packagers to build
4218 complete functionality into the libguestfs appliance.
4219 Upstream libguestfs, if built from source with all
4220 requirements satisfied, will support everything.
4221
4222 =item *
4223
4224 This call was added in version C<1.0.80>.  In previous
4225 versions of libguestfs all you could do would be to speculatively
4226 execute a command to find out if the daemon implemented it.
4227 See also C<guestfs_version>.
4228
4229 =back");
4230
4231   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4232    [InitBasicFS, Always, TestOutputBuffer (
4233       [["write_file"; "/src"; "hello, world"; "0"];
4234        ["dd"; "/src"; "/dest"];
4235        ["read_file"; "/dest"]], "hello, world")],
4236    "copy from source to destination using dd",
4237    "\
4238 This command copies from one source device or file C<src>
4239 to another destination device or file C<dest>.  Normally you
4240 would use this to copy to or from a device or partition, for
4241 example to duplicate a filesystem.
4242
4243 If the destination is a device, it must be as large or larger
4244 than the source file or device, otherwise the copy will fail.
4245 This command cannot do partial copies (see C<guestfs_copy_size>).");
4246
4247   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4248    [InitBasicFS, Always, TestOutputInt (
4249       [["write_file"; "/file"; "hello, world"; "0"];
4250        ["filesize"; "/file"]], 12)],
4251    "return the size of the file in bytes",
4252    "\
4253 This command returns the size of C<file> in bytes.
4254
4255 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4256 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4257 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4258
4259   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4260    [InitBasicFSonLVM, Always, TestOutputList (
4261       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4262        ["lvs"]], ["/dev/VG/LV2"])],
4263    "rename an LVM logical volume",
4264    "\
4265 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4266
4267   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4268    [InitBasicFSonLVM, Always, TestOutputList (
4269       [["umount"; "/"];
4270        ["vg_activate"; "false"; "VG"];
4271        ["vgrename"; "VG"; "VG2"];
4272        ["vg_activate"; "true"; "VG2"];
4273        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4274        ["vgs"]], ["VG2"])],
4275    "rename an LVM volume group",
4276    "\
4277 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4278
4279   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4280    [InitISOFS, Always, TestOutputBuffer (
4281       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4282    "list the contents of a single file in an initrd",
4283    "\
4284 This command unpacks the file C<filename> from the initrd file
4285 called C<initrdpath>.  The filename must be given I<without> the
4286 initial C</> character.
4287
4288 For example, in guestfish you could use the following command
4289 to examine the boot script (usually called C</init>)
4290 contained in a Linux initrd or initramfs image:
4291
4292  initrd-cat /boot/initrd-<version>.img init
4293
4294 See also C<guestfs_initrd_list>.");
4295
4296   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4297    [],
4298    "get the UUID of a physical volume",
4299    "\
4300 This command returns the UUID of the LVM PV C<device>.");
4301
4302   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4303    [],
4304    "get the UUID of a volume group",
4305    "\
4306 This command returns the UUID of the LVM VG named C<vgname>.");
4307
4308   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4309    [],
4310    "get the UUID of a logical volume",
4311    "\
4312 This command returns the UUID of the LVM LV C<device>.");
4313
4314   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4315    [],
4316    "get the PV UUIDs containing the volume group",
4317    "\
4318 Given a VG called C<vgname>, this returns the UUIDs of all
4319 the physical volumes that this volume group resides on.
4320
4321 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4322 calls to associate physical volumes and volume groups.
4323
4324 See also C<guestfs_vglvuuids>.");
4325
4326   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4327    [],
4328    "get the LV UUIDs of all LVs in the volume group",
4329    "\
4330 Given a VG called C<vgname>, this returns the UUIDs of all
4331 the logical volumes created in this volume group.
4332
4333 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4334 calls to associate logical volumes and volume groups.
4335
4336 See also C<guestfs_vgpvuuids>.");
4337
4338   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4339    [InitBasicFS, Always, TestOutputBuffer (
4340       [["write_file"; "/src"; "hello, world"; "0"];
4341        ["copy_size"; "/src"; "/dest"; "5"];
4342        ["read_file"; "/dest"]], "hello")],
4343    "copy size bytes from source to destination using dd",
4344    "\
4345 This command copies exactly C<size> bytes from one source device
4346 or file C<src> to another destination device or file C<dest>.
4347
4348 Note this will fail if the source is too short or if the destination
4349 is not large enough.");
4350
4351   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4352    [InitBasicFSonLVM, Always, TestRun (
4353       [["zero_device"; "/dev/VG/LV"]])],
4354    "write zeroes to an entire device",
4355    "\
4356 This command writes zeroes over the entire C<device>.  Compare
4357 with C<guestfs_zero> which just zeroes the first few blocks of
4358 a device.");
4359
4360   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4361    [InitBasicFS, Always, TestOutput (
4362       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4363        ["cat"; "/hello"]], "hello\n")],
4364    "unpack compressed tarball to directory",
4365    "\
4366 This command uploads and unpacks local file C<tarball> (an
4367 I<xz compressed> tar file) into C<directory>.");
4368
4369   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4370    [],
4371    "pack directory into compressed tarball",
4372    "\
4373 This command packs the contents of C<directory> and downloads
4374 it to local file C<tarball> (as an xz compressed tar archive).");
4375
4376   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4377    [],
4378    "resize an NTFS filesystem",
4379    "\
4380 This command resizes an NTFS filesystem, expanding or
4381 shrinking it to the size of the underlying device.
4382 See also L<ntfsresize(8)>.");
4383
4384   ("vgscan", (RErr, []), 232, [],
4385    [InitEmpty, Always, TestRun (
4386       [["vgscan"]])],
4387    "rescan for LVM physical volumes, volume groups and logical volumes",
4388    "\
4389 This rescans all block devices and rebuilds the list of LVM
4390 physical volumes, volume groups and logical volumes.");
4391
4392 ]
4393
4394 let all_functions = non_daemon_functions @ daemon_functions
4395
4396 (* In some places we want the functions to be displayed sorted
4397  * alphabetically, so this is useful:
4398  *)
4399 let all_functions_sorted =
4400   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4401                compare n1 n2) all_functions
4402
4403 (* Field types for structures. *)
4404 type field =
4405   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4406   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4407   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4408   | FUInt32
4409   | FInt32
4410   | FUInt64
4411   | FInt64
4412   | FBytes                      (* Any int measure that counts bytes. *)
4413   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4414   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4415
4416 (* Because we generate extra parsing code for LVM command line tools,
4417  * we have to pull out the LVM columns separately here.
4418  *)
4419 let lvm_pv_cols = [
4420   "pv_name", FString;
4421   "pv_uuid", FUUID;
4422   "pv_fmt", FString;
4423   "pv_size", FBytes;
4424   "dev_size", FBytes;
4425   "pv_free", FBytes;
4426   "pv_used", FBytes;
4427   "pv_attr", FString (* XXX *);
4428   "pv_pe_count", FInt64;
4429   "pv_pe_alloc_count", FInt64;
4430   "pv_tags", FString;
4431   "pe_start", FBytes;
4432   "pv_mda_count", FInt64;
4433   "pv_mda_free", FBytes;
4434   (* Not in Fedora 10:
4435      "pv_mda_size", FBytes;
4436   *)
4437 ]
4438 let lvm_vg_cols = [
4439   "vg_name", FString;
4440   "vg_uuid", FUUID;
4441   "vg_fmt", FString;
4442   "vg_attr", FString (* XXX *);
4443   "vg_size", FBytes;
4444   "vg_free", FBytes;
4445   "vg_sysid", FString;
4446   "vg_extent_size", FBytes;
4447   "vg_extent_count", FInt64;
4448   "vg_free_count", FInt64;
4449   "max_lv", FInt64;
4450   "max_pv", FInt64;
4451   "pv_count", FInt64;
4452   "lv_count", FInt64;
4453   "snap_count", FInt64;
4454   "vg_seqno", FInt64;
4455   "vg_tags", FString;
4456   "vg_mda_count", FInt64;
4457   "vg_mda_free", FBytes;
4458   (* Not in Fedora 10:
4459      "vg_mda_size", FBytes;
4460   *)
4461 ]
4462 let lvm_lv_cols = [
4463   "lv_name", FString;
4464   "lv_uuid", FUUID;
4465   "lv_attr", FString (* XXX *);
4466   "lv_major", FInt64;
4467   "lv_minor", FInt64;
4468   "lv_kernel_major", FInt64;
4469   "lv_kernel_minor", FInt64;
4470   "lv_size", FBytes;
4471   "seg_count", FInt64;
4472   "origin", FString;
4473   "snap_percent", FOptPercent;
4474   "copy_percent", FOptPercent;
4475   "move_pv", FString;
4476   "lv_tags", FString;
4477   "mirror_log", FString;
4478   "modules", FString;
4479 ]
4480
4481 (* Names and fields in all structures (in RStruct and RStructList)
4482  * that we support.
4483  *)
4484 let structs = [
4485   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4486    * not use this struct in any new code.
4487    *)
4488   "int_bool", [
4489     "i", FInt32;                (* for historical compatibility *)
4490     "b", FInt32;                (* for historical compatibility *)
4491   ];
4492
4493   (* LVM PVs, VGs, LVs. *)
4494   "lvm_pv", lvm_pv_cols;
4495   "lvm_vg", lvm_vg_cols;
4496   "lvm_lv", lvm_lv_cols;
4497
4498   (* Column names and types from stat structures.
4499    * NB. Can't use things like 'st_atime' because glibc header files
4500    * define some of these as macros.  Ugh.
4501    *)
4502   "stat", [
4503     "dev", FInt64;
4504     "ino", FInt64;
4505     "mode", FInt64;
4506     "nlink", FInt64;
4507     "uid", FInt64;
4508     "gid", FInt64;
4509     "rdev", FInt64;
4510     "size", FInt64;
4511     "blksize", FInt64;
4512     "blocks", FInt64;
4513     "atime", FInt64;
4514     "mtime", FInt64;
4515     "ctime", FInt64;
4516   ];
4517   "statvfs", [
4518     "bsize", FInt64;
4519     "frsize", FInt64;
4520     "blocks", FInt64;
4521     "bfree", FInt64;
4522     "bavail", FInt64;
4523     "files", FInt64;
4524     "ffree", FInt64;
4525     "favail", FInt64;
4526     "fsid", FInt64;
4527     "flag", FInt64;
4528     "namemax", FInt64;
4529   ];
4530
4531   (* Column names in dirent structure. *)
4532   "dirent", [
4533     "ino", FInt64;
4534     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4535     "ftyp", FChar;
4536     "name", FString;
4537   ];
4538
4539   (* Version numbers. *)
4540   "version", [
4541     "major", FInt64;
4542     "minor", FInt64;
4543     "release", FInt64;
4544     "extra", FString;
4545   ];
4546
4547   (* Extended attribute. *)
4548   "xattr", [
4549     "attrname", FString;
4550     "attrval", FBuffer;
4551   ];
4552
4553   (* Inotify events. *)
4554   "inotify_event", [
4555     "in_wd", FInt64;
4556     "in_mask", FUInt32;
4557     "in_cookie", FUInt32;
4558     "in_name", FString;
4559   ];
4560
4561   (* Partition table entry. *)
4562   "partition", [
4563     "part_num", FInt32;
4564     "part_start", FBytes;
4565     "part_end", FBytes;
4566     "part_size", FBytes;
4567   ];
4568 ] (* end of structs *)
4569
4570 (* Ugh, Java has to be different ..
4571  * These names are also used by the Haskell bindings.
4572  *)
4573 let java_structs = [
4574   "int_bool", "IntBool";
4575   "lvm_pv", "PV";
4576   "lvm_vg", "VG";
4577   "lvm_lv", "LV";
4578   "stat", "Stat";
4579   "statvfs", "StatVFS";
4580   "dirent", "Dirent";
4581   "version", "Version";
4582   "xattr", "XAttr";
4583   "inotify_event", "INotifyEvent";
4584   "partition", "Partition";
4585 ]
4586
4587 (* What structs are actually returned. *)
4588 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4589
4590 (* Returns a list of RStruct/RStructList structs that are returned
4591  * by any function.  Each element of returned list is a pair:
4592  *
4593  * (structname, RStructOnly)
4594  *    == there exists function which returns RStruct (_, structname)
4595  * (structname, RStructListOnly)
4596  *    == there exists function which returns RStructList (_, structname)
4597  * (structname, RStructAndList)
4598  *    == there are functions returning both RStruct (_, structname)
4599  *                                      and RStructList (_, structname)
4600  *)
4601 let rstructs_used_by functions =
4602   (* ||| is a "logical OR" for rstructs_used_t *)
4603   let (|||) a b =
4604     match a, b with
4605     | RStructAndList, _
4606     | _, RStructAndList -> RStructAndList
4607     | RStructOnly, RStructListOnly
4608     | RStructListOnly, RStructOnly -> RStructAndList
4609     | RStructOnly, RStructOnly -> RStructOnly
4610     | RStructListOnly, RStructListOnly -> RStructListOnly
4611   in
4612
4613   let h = Hashtbl.create 13 in
4614
4615   (* if elem->oldv exists, update entry using ||| operator,
4616    * else just add elem->newv to the hash
4617    *)
4618   let update elem newv =
4619     try  let oldv = Hashtbl.find h elem in
4620          Hashtbl.replace h elem (newv ||| oldv)
4621     with Not_found -> Hashtbl.add h elem newv
4622   in
4623
4624   List.iter (
4625     fun (_, style, _, _, _, _, _) ->
4626       match fst style with
4627       | RStruct (_, structname) -> update structname RStructOnly
4628       | RStructList (_, structname) -> update structname RStructListOnly
4629       | _ -> ()
4630   ) functions;
4631
4632   (* return key->values as a list of (key,value) *)
4633   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4634
4635 (* Used for testing language bindings. *)
4636 type callt =
4637   | CallString of string
4638   | CallOptString of string option
4639   | CallStringList of string list
4640   | CallInt of int
4641   | CallInt64 of int64
4642   | CallBool of bool
4643
4644 (* Used to memoize the result of pod2text. *)
4645 let pod2text_memo_filename = "src/.pod2text.data"
4646 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4647   try
4648     let chan = open_in pod2text_memo_filename in
4649     let v = input_value chan in
4650     close_in chan;
4651     v
4652   with
4653     _ -> Hashtbl.create 13
4654 let pod2text_memo_updated () =
4655   let chan = open_out pod2text_memo_filename in
4656   output_value chan pod2text_memo;
4657   close_out chan
4658
4659 (* Useful functions.
4660  * Note we don't want to use any external OCaml libraries which
4661  * makes this a bit harder than it should be.
4662  *)
4663 module StringMap = Map.Make (String)
4664
4665 let failwithf fs = ksprintf failwith fs
4666
4667 let unique = let i = ref 0 in fun () -> incr i; !i
4668
4669 let replace_char s c1 c2 =
4670   let s2 = String.copy s in
4671   let r = ref false in
4672   for i = 0 to String.length s2 - 1 do
4673     if String.unsafe_get s2 i = c1 then (
4674       String.unsafe_set s2 i c2;
4675       r := true
4676     )
4677   done;
4678   if not !r then s else s2
4679
4680 let isspace c =
4681   c = ' '
4682   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4683
4684 let triml ?(test = isspace) str =
4685   let i = ref 0 in
4686   let n = ref (String.length str) in
4687   while !n > 0 && test str.[!i]; do
4688     decr n;
4689     incr i
4690   done;
4691   if !i = 0 then str
4692   else String.sub str !i !n
4693
4694 let trimr ?(test = isspace) str =
4695   let n = ref (String.length str) in
4696   while !n > 0 && test str.[!n-1]; do
4697     decr n
4698   done;
4699   if !n = String.length str then str
4700   else String.sub str 0 !n
4701
4702 let trim ?(test = isspace) str =
4703   trimr ~test (triml ~test str)
4704
4705 let rec find s sub =
4706   let len = String.length s in
4707   let sublen = String.length sub in
4708   let rec loop i =
4709     if i <= len-sublen then (
4710       let rec loop2 j =
4711         if j < sublen then (
4712           if s.[i+j] = sub.[j] then loop2 (j+1)
4713           else -1
4714         ) else
4715           i (* found *)
4716       in
4717       let r = loop2 0 in
4718       if r = -1 then loop (i+1) else r
4719     ) else
4720       -1 (* not found *)
4721   in
4722   loop 0
4723
4724 let rec replace_str s s1 s2 =
4725   let len = String.length s in
4726   let sublen = String.length s1 in
4727   let i = find s s1 in
4728   if i = -1 then s
4729   else (
4730     let s' = String.sub s 0 i in
4731     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4732     s' ^ s2 ^ replace_str s'' s1 s2
4733   )
4734
4735 let rec string_split sep str =
4736   let len = String.length str in
4737   let seplen = String.length sep in
4738   let i = find str sep in
4739   if i = -1 then [str]
4740   else (
4741     let s' = String.sub str 0 i in
4742     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4743     s' :: string_split sep s''
4744   )
4745
4746 let files_equal n1 n2 =
4747   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4748   match Sys.command cmd with
4749   | 0 -> true
4750   | 1 -> false
4751   | i -> failwithf "%s: failed with error code %d" cmd i
4752
4753 let rec filter_map f = function
4754   | [] -> []
4755   | x :: xs ->
4756       match f x with
4757       | Some y -> y :: filter_map f xs
4758       | None -> filter_map f xs
4759
4760 let rec find_map f = function
4761   | [] -> raise Not_found
4762   | x :: xs ->
4763       match f x with
4764       | Some y -> y
4765       | None -> find_map f xs
4766
4767 let iteri f xs =
4768   let rec loop i = function
4769     | [] -> ()
4770     | x :: xs -> f i x; loop (i+1) xs
4771   in
4772   loop 0 xs
4773
4774 let mapi f xs =
4775   let rec loop i = function
4776     | [] -> []
4777     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4778   in
4779   loop 0 xs
4780
4781 let count_chars c str =
4782   let count = ref 0 in
4783   for i = 0 to String.length str - 1 do
4784     if c = String.unsafe_get str i then incr count
4785   done;
4786   !count
4787
4788 let name_of_argt = function
4789   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4790   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4791   | FileIn n | FileOut n -> n
4792
4793 let java_name_of_struct typ =
4794   try List.assoc typ java_structs
4795   with Not_found ->
4796     failwithf
4797       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4798
4799 let cols_of_struct typ =
4800   try List.assoc typ structs
4801   with Not_found ->
4802     failwithf "cols_of_struct: unknown struct %s" typ
4803
4804 let seq_of_test = function
4805   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4806   | TestOutputListOfDevices (s, _)
4807   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4808   | TestOutputTrue s | TestOutputFalse s
4809   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4810   | TestOutputStruct (s, _)
4811   | TestLastFail s -> s
4812
4813 (* Handling for function flags. *)
4814 let protocol_limit_warning =
4815   "Because of the message protocol, there is a transfer limit
4816 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4817
4818 let danger_will_robinson =
4819   "B<This command is dangerous.  Without careful use you
4820 can easily destroy all your data>."
4821
4822 let deprecation_notice flags =
4823   try
4824     let alt =
4825       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4826     let txt =
4827       sprintf "This function is deprecated.
4828 In new code, use the C<%s> call instead.
4829
4830 Deprecated functions will not be removed from the API, but the
4831 fact that they are deprecated indicates that there are problems
4832 with correct use of these functions." alt in
4833     Some txt
4834   with
4835     Not_found -> None
4836
4837 (* Create list of optional groups. *)
4838 let optgroups =
4839   let h = Hashtbl.create 13 in
4840   List.iter (
4841     fun (name, _, _, flags, _, _, _) ->
4842       List.iter (
4843         function
4844         | Optional group ->
4845             let names = try Hashtbl.find h group with Not_found -> [] in
4846             Hashtbl.replace h group (name :: names)
4847         | _ -> ()
4848       ) flags
4849   ) daemon_functions;
4850   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4851   let groups =
4852     List.map (
4853       fun group -> group, List.sort compare (Hashtbl.find h group)
4854     ) groups in
4855   List.sort (fun x y -> compare (fst x) (fst y)) groups
4856
4857 (* Check function names etc. for consistency. *)
4858 let check_functions () =
4859   let contains_uppercase str =
4860     let len = String.length str in
4861     let rec loop i =
4862       if i >= len then false
4863       else (
4864         let c = str.[i] in
4865         if c >= 'A' && c <= 'Z' then true
4866         else loop (i+1)
4867       )
4868     in
4869     loop 0
4870   in
4871
4872   (* Check function names. *)
4873   List.iter (
4874     fun (name, _, _, _, _, _, _) ->
4875       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4876         failwithf "function name %s does not need 'guestfs' prefix" name;
4877       if name = "" then
4878         failwithf "function name is empty";
4879       if name.[0] < 'a' || name.[0] > 'z' then
4880         failwithf "function name %s must start with lowercase a-z" name;
4881       if String.contains name '-' then
4882         failwithf "function name %s should not contain '-', use '_' instead."
4883           name
4884   ) all_functions;
4885
4886   (* Check function parameter/return names. *)
4887   List.iter (
4888     fun (name, style, _, _, _, _, _) ->
4889       let check_arg_ret_name n =
4890         if contains_uppercase n then
4891           failwithf "%s param/ret %s should not contain uppercase chars"
4892             name n;
4893         if String.contains n '-' || String.contains n '_' then
4894           failwithf "%s param/ret %s should not contain '-' or '_'"
4895             name n;
4896         if n = "value" then
4897           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;
4898         if n = "int" || n = "char" || n = "short" || n = "long" then
4899           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4900         if n = "i" || n = "n" then
4901           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4902         if n = "argv" || n = "args" then
4903           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4904
4905         (* List Haskell, OCaml and C keywords here.
4906          * http://www.haskell.org/haskellwiki/Keywords
4907          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4908          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4909          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4910          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4911          * Omitting _-containing words, since they're handled above.
4912          * Omitting the OCaml reserved word, "val", is ok,
4913          * and saves us from renaming several parameters.
4914          *)
4915         let reserved = [
4916           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4917           "char"; "class"; "const"; "constraint"; "continue"; "data";
4918           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4919           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4920           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4921           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4922           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4923           "interface";
4924           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4925           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4926           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4927           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4928           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4929           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4930           "volatile"; "when"; "where"; "while";
4931           ] in
4932         if List.mem n reserved then
4933           failwithf "%s has param/ret using reserved word %s" name n;
4934       in
4935
4936       (match fst style with
4937        | RErr -> ()
4938        | RInt n | RInt64 n | RBool n
4939        | RConstString n | RConstOptString n | RString n
4940        | RStringList n | RStruct (n, _) | RStructList (n, _)
4941        | RHashtable n | RBufferOut n ->
4942            check_arg_ret_name n
4943       );
4944       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4945   ) all_functions;
4946
4947   (* Check short descriptions. *)
4948   List.iter (
4949     fun (name, _, _, _, _, shortdesc, _) ->
4950       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4951         failwithf "short description of %s should begin with lowercase." name;
4952       let c = shortdesc.[String.length shortdesc-1] in
4953       if c = '\n' || c = '.' then
4954         failwithf "short description of %s should not end with . or \\n." name
4955   ) all_functions;
4956
4957   (* Check long dscriptions. *)
4958   List.iter (
4959     fun (name, _, _, _, _, _, longdesc) ->
4960       if longdesc.[String.length longdesc-1] = '\n' then
4961         failwithf "long description of %s should not end with \\n." name
4962   ) all_functions;
4963
4964   (* Check proc_nrs. *)
4965   List.iter (
4966     fun (name, _, proc_nr, _, _, _, _) ->
4967       if proc_nr <= 0 then
4968         failwithf "daemon function %s should have proc_nr > 0" name
4969   ) daemon_functions;
4970
4971   List.iter (
4972     fun (name, _, proc_nr, _, _, _, _) ->
4973       if proc_nr <> -1 then
4974         failwithf "non-daemon function %s should have proc_nr -1" name
4975   ) non_daemon_functions;
4976
4977   let proc_nrs =
4978     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4979       daemon_functions in
4980   let proc_nrs =
4981     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4982   let rec loop = function
4983     | [] -> ()
4984     | [_] -> ()
4985     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4986         loop rest
4987     | (name1,nr1) :: (name2,nr2) :: _ ->
4988         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4989           name1 name2 nr1 nr2
4990   in
4991   loop proc_nrs;
4992
4993   (* Check tests. *)
4994   List.iter (
4995     function
4996       (* Ignore functions that have no tests.  We generate a
4997        * warning when the user does 'make check' instead.
4998        *)
4999     | name, _, _, _, [], _, _ -> ()
5000     | name, _, _, _, tests, _, _ ->
5001         let funcs =
5002           List.map (
5003             fun (_, _, test) ->
5004               match seq_of_test test with
5005               | [] ->
5006                   failwithf "%s has a test containing an empty sequence" name
5007               | cmds -> List.map List.hd cmds
5008           ) tests in
5009         let funcs = List.flatten funcs in
5010
5011         let tested = List.mem name funcs in
5012
5013         if not tested then
5014           failwithf "function %s has tests but does not test itself" name
5015   ) all_functions
5016
5017 (* 'pr' prints to the current output file. *)
5018 let chan = ref Pervasives.stdout
5019 let lines = ref 0
5020 let pr fs =
5021   ksprintf
5022     (fun str ->
5023        let i = count_chars '\n' str in
5024        lines := !lines + i;
5025        output_string !chan str
5026     ) fs
5027
5028 let copyright_years =
5029   let this_year = 1900 + (localtime (time ())).tm_year in
5030   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5031
5032 (* Generate a header block in a number of standard styles. *)
5033 type comment_style =
5034     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5035 type license = GPLv2plus | LGPLv2plus
5036
5037 let generate_header ?(extra_inputs = []) comment license =
5038   let inputs = "src/generator.ml" :: extra_inputs in
5039   let c = match comment with
5040     | CStyle ->         pr "/* "; " *"
5041     | CPlusPlusStyle -> pr "// "; "//"
5042     | HashStyle ->      pr "# ";  "#"
5043     | OCamlStyle ->     pr "(* "; " *"
5044     | HaskellStyle ->   pr "{- "; "  " in
5045   pr "libguestfs generated file\n";
5046   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5047   List.iter (pr "%s   %s\n" c) inputs;
5048   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5049   pr "%s\n" c;
5050   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5051   pr "%s\n" c;
5052   (match license with
5053    | GPLv2plus ->
5054        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5055        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5056        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5057        pr "%s (at your option) any later version.\n" c;
5058        pr "%s\n" c;
5059        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5060        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5061        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5062        pr "%s GNU General Public License for more details.\n" c;
5063        pr "%s\n" c;
5064        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5065        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5066        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5067
5068    | LGPLv2plus ->
5069        pr "%s This library is free software; you can redistribute it and/or\n" c;
5070        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5071        pr "%s License as published by the Free Software Foundation; either\n" c;
5072        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5073        pr "%s\n" c;
5074        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5075        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5076        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5077        pr "%s Lesser General Public License for more details.\n" c;
5078        pr "%s\n" c;
5079        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5080        pr "%s License along with this library; if not, write to the Free Software\n" c;
5081        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5082   );
5083   (match comment with
5084    | CStyle -> pr " */\n"
5085    | CPlusPlusStyle
5086    | HashStyle -> ()
5087    | OCamlStyle -> pr " *)\n"
5088    | HaskellStyle -> pr "-}\n"
5089   );
5090   pr "\n"
5091
5092 (* Start of main code generation functions below this line. *)
5093
5094 (* Generate the pod documentation for the C API. *)
5095 let rec generate_actions_pod () =
5096   List.iter (
5097     fun (shortname, style, _, flags, _, _, longdesc) ->
5098       if not (List.mem NotInDocs flags) then (
5099         let name = "guestfs_" ^ shortname in
5100         pr "=head2 %s\n\n" name;
5101         pr " ";
5102         generate_prototype ~extern:false ~handle:"handle" name style;
5103         pr "\n\n";
5104         pr "%s\n\n" longdesc;
5105         (match fst style with
5106          | RErr ->
5107              pr "This function returns 0 on success or -1 on error.\n\n"
5108          | RInt _ ->
5109              pr "On error this function returns -1.\n\n"
5110          | RInt64 _ ->
5111              pr "On error this function returns -1.\n\n"
5112          | RBool _ ->
5113              pr "This function returns a C truth value on success or -1 on error.\n\n"
5114          | RConstString _ ->
5115              pr "This function returns a string, or NULL on error.
5116 The string is owned by the guest handle and must I<not> be freed.\n\n"
5117          | RConstOptString _ ->
5118              pr "This function returns a string which may be NULL.
5119 There is way to return an error from this function.
5120 The string is owned by the guest handle and must I<not> be freed.\n\n"
5121          | RString _ ->
5122              pr "This function returns a string, or NULL on error.
5123 I<The caller must free the returned string after use>.\n\n"
5124          | RStringList _ ->
5125              pr "This function returns a NULL-terminated array of strings
5126 (like L<environ(3)>), or NULL if there was an error.
5127 I<The caller must free the strings and the array after use>.\n\n"
5128          | RStruct (_, typ) ->
5129              pr "This function returns a C<struct guestfs_%s *>,
5130 or NULL if there was an error.
5131 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5132          | RStructList (_, typ) ->
5133              pr "This function returns a C<struct guestfs_%s_list *>
5134 (see E<lt>guestfs-structs.hE<gt>),
5135 or NULL if there was an error.
5136 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5137          | RHashtable _ ->
5138              pr "This function returns a NULL-terminated array of
5139 strings, or NULL if there was an error.
5140 The array of strings will always have length C<2n+1>, where
5141 C<n> keys and values alternate, followed by the trailing NULL entry.
5142 I<The caller must free the strings and the array after use>.\n\n"
5143          | RBufferOut _ ->
5144              pr "This function returns a buffer, or NULL on error.
5145 The size of the returned buffer is written to C<*size_r>.
5146 I<The caller must free the returned buffer after use>.\n\n"
5147         );
5148         if List.mem ProtocolLimitWarning flags then
5149           pr "%s\n\n" protocol_limit_warning;
5150         if List.mem DangerWillRobinson flags then
5151           pr "%s\n\n" danger_will_robinson;
5152         match deprecation_notice flags with
5153         | None -> ()
5154         | Some txt -> pr "%s\n\n" txt
5155       )
5156   ) all_functions_sorted
5157
5158 and generate_structs_pod () =
5159   (* Structs documentation. *)
5160   List.iter (
5161     fun (typ, cols) ->
5162       pr "=head2 guestfs_%s\n" typ;
5163       pr "\n";
5164       pr " struct guestfs_%s {\n" typ;
5165       List.iter (
5166         function
5167         | name, FChar -> pr "   char %s;\n" name
5168         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5169         | name, FInt32 -> pr "   int32_t %s;\n" name
5170         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5171         | name, FInt64 -> pr "   int64_t %s;\n" name
5172         | name, FString -> pr "   char *%s;\n" name
5173         | name, FBuffer ->
5174             pr "   /* The next two fields describe a byte array. */\n";
5175             pr "   uint32_t %s_len;\n" name;
5176             pr "   char *%s;\n" name
5177         | name, FUUID ->
5178             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5179             pr "   char %s[32];\n" name
5180         | name, FOptPercent ->
5181             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5182             pr "   float %s;\n" name
5183       ) cols;
5184       pr " };\n";
5185       pr " \n";
5186       pr " struct guestfs_%s_list {\n" typ;
5187       pr "   uint32_t len; /* Number of elements in list. */\n";
5188       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5189       pr " };\n";
5190       pr " \n";
5191       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5192       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5193         typ typ;
5194       pr "\n"
5195   ) structs
5196
5197 and generate_availability_pod () =
5198   (* Availability documentation. *)
5199   pr "=over 4\n";
5200   pr "\n";
5201   List.iter (
5202     fun (group, functions) ->
5203       pr "=item B<%s>\n" group;
5204       pr "\n";
5205       pr "The following functions:\n";
5206       List.iter (pr "L</guestfs_%s>\n") functions;
5207       pr "\n"
5208   ) optgroups;
5209   pr "=back\n";
5210   pr "\n"
5211
5212 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5213  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5214  *
5215  * We have to use an underscore instead of a dash because otherwise
5216  * rpcgen generates incorrect code.
5217  *
5218  * This header is NOT exported to clients, but see also generate_structs_h.
5219  *)
5220 and generate_xdr () =
5221   generate_header CStyle LGPLv2plus;
5222
5223   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5224   pr "typedef string str<>;\n";
5225   pr "\n";
5226
5227   (* Internal structures. *)
5228   List.iter (
5229     function
5230     | typ, cols ->
5231         pr "struct guestfs_int_%s {\n" typ;
5232         List.iter (function
5233                    | name, FChar -> pr "  char %s;\n" name
5234                    | name, FString -> pr "  string %s<>;\n" name
5235                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5236                    | name, FUUID -> pr "  opaque %s[32];\n" name
5237                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5238                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5239                    | name, FOptPercent -> pr "  float %s;\n" name
5240                   ) cols;
5241         pr "};\n";
5242         pr "\n";
5243         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5244         pr "\n";
5245   ) structs;
5246
5247   List.iter (
5248     fun (shortname, style, _, _, _, _, _) ->
5249       let name = "guestfs_" ^ shortname in
5250
5251       (match snd style with
5252        | [] -> ()
5253        | args ->
5254            pr "struct %s_args {\n" name;
5255            List.iter (
5256              function
5257              | Pathname n | Device n | Dev_or_Path n | String n ->
5258                  pr "  string %s<>;\n" n
5259              | OptString n -> pr "  str *%s;\n" n
5260              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5261              | Bool n -> pr "  bool %s;\n" n
5262              | Int n -> pr "  int %s;\n" n
5263              | Int64 n -> pr "  hyper %s;\n" n
5264              | FileIn _ | FileOut _ -> ()
5265            ) args;
5266            pr "};\n\n"
5267       );
5268       (match fst style with
5269        | RErr -> ()
5270        | RInt n ->
5271            pr "struct %s_ret {\n" name;
5272            pr "  int %s;\n" n;
5273            pr "};\n\n"
5274        | RInt64 n ->
5275            pr "struct %s_ret {\n" name;
5276            pr "  hyper %s;\n" n;
5277            pr "};\n\n"
5278        | RBool n ->
5279            pr "struct %s_ret {\n" name;
5280            pr "  bool %s;\n" n;
5281            pr "};\n\n"
5282        | RConstString _ | RConstOptString _ ->
5283            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5284        | RString n ->
5285            pr "struct %s_ret {\n" name;
5286            pr "  string %s<>;\n" n;
5287            pr "};\n\n"
5288        | RStringList n ->
5289            pr "struct %s_ret {\n" name;
5290            pr "  str %s<>;\n" n;
5291            pr "};\n\n"
5292        | RStruct (n, typ) ->
5293            pr "struct %s_ret {\n" name;
5294            pr "  guestfs_int_%s %s;\n" typ n;
5295            pr "};\n\n"
5296        | RStructList (n, typ) ->
5297            pr "struct %s_ret {\n" name;
5298            pr "  guestfs_int_%s_list %s;\n" typ n;
5299            pr "};\n\n"
5300        | RHashtable n ->
5301            pr "struct %s_ret {\n" name;
5302            pr "  str %s<>;\n" n;
5303            pr "};\n\n"
5304        | RBufferOut n ->
5305            pr "struct %s_ret {\n" name;
5306            pr "  opaque %s<>;\n" n;
5307            pr "};\n\n"
5308       );
5309   ) daemon_functions;
5310
5311   (* Table of procedure numbers. *)
5312   pr "enum guestfs_procedure {\n";
5313   List.iter (
5314     fun (shortname, _, proc_nr, _, _, _, _) ->
5315       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5316   ) daemon_functions;
5317   pr "  GUESTFS_PROC_NR_PROCS\n";
5318   pr "};\n";
5319   pr "\n";
5320
5321   (* Having to choose a maximum message size is annoying for several
5322    * reasons (it limits what we can do in the API), but it (a) makes
5323    * the protocol a lot simpler, and (b) provides a bound on the size
5324    * of the daemon which operates in limited memory space.
5325    *)
5326   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5327   pr "\n";
5328
5329   (* Message header, etc. *)
5330   pr "\
5331 /* The communication protocol is now documented in the guestfs(3)
5332  * manpage.
5333  */
5334
5335 const GUESTFS_PROGRAM = 0x2000F5F5;
5336 const GUESTFS_PROTOCOL_VERSION = 1;
5337
5338 /* These constants must be larger than any possible message length. */
5339 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5340 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5341
5342 enum guestfs_message_direction {
5343   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5344   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5345 };
5346
5347 enum guestfs_message_status {
5348   GUESTFS_STATUS_OK = 0,
5349   GUESTFS_STATUS_ERROR = 1
5350 };
5351
5352 const GUESTFS_ERROR_LEN = 256;
5353
5354 struct guestfs_message_error {
5355   string error_message<GUESTFS_ERROR_LEN>;
5356 };
5357
5358 struct guestfs_message_header {
5359   unsigned prog;                     /* GUESTFS_PROGRAM */
5360   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5361   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5362   guestfs_message_direction direction;
5363   unsigned serial;                   /* message serial number */
5364   guestfs_message_status status;
5365 };
5366
5367 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5368
5369 struct guestfs_chunk {
5370   int cancel;                        /* if non-zero, transfer is cancelled */
5371   /* data size is 0 bytes if the transfer has finished successfully */
5372   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5373 };
5374 "
5375
5376 (* Generate the guestfs-structs.h file. *)
5377 and generate_structs_h () =
5378   generate_header CStyle LGPLv2plus;
5379
5380   (* This is a public exported header file containing various
5381    * structures.  The structures are carefully written to have
5382    * exactly the same in-memory format as the XDR structures that
5383    * we use on the wire to the daemon.  The reason for creating
5384    * copies of these structures here is just so we don't have to
5385    * export the whole of guestfs_protocol.h (which includes much
5386    * unrelated and XDR-dependent stuff that we don't want to be
5387    * public, or required by clients).
5388    *
5389    * To reiterate, we will pass these structures to and from the
5390    * client with a simple assignment or memcpy, so the format
5391    * must be identical to what rpcgen / the RFC defines.
5392    *)
5393
5394   (* Public structures. *)
5395   List.iter (
5396     fun (typ, cols) ->
5397       pr "struct guestfs_%s {\n" typ;
5398       List.iter (
5399         function
5400         | name, FChar -> pr "  char %s;\n" name
5401         | name, FString -> pr "  char *%s;\n" name
5402         | name, FBuffer ->
5403             pr "  uint32_t %s_len;\n" name;
5404             pr "  char *%s;\n" name
5405         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5406         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5407         | name, FInt32 -> pr "  int32_t %s;\n" name
5408         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5409         | name, FInt64 -> pr "  int64_t %s;\n" name
5410         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5411       ) cols;
5412       pr "};\n";
5413       pr "\n";
5414       pr "struct guestfs_%s_list {\n" typ;
5415       pr "  uint32_t len;\n";
5416       pr "  struct guestfs_%s *val;\n" typ;
5417       pr "};\n";
5418       pr "\n";
5419       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5420       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5421       pr "\n"
5422   ) structs
5423
5424 (* Generate the guestfs-actions.h file. *)
5425 and generate_actions_h () =
5426   generate_header CStyle LGPLv2plus;
5427   List.iter (
5428     fun (shortname, style, _, _, _, _, _) ->
5429       let name = "guestfs_" ^ shortname in
5430       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5431         name style
5432   ) all_functions
5433
5434 (* Generate the guestfs-internal-actions.h file. *)
5435 and generate_internal_actions_h () =
5436   generate_header CStyle LGPLv2plus;
5437   List.iter (
5438     fun (shortname, style, _, _, _, _, _) ->
5439       let name = "guestfs__" ^ shortname in
5440       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5441         name style
5442   ) non_daemon_functions
5443
5444 (* Generate the client-side dispatch stubs. *)
5445 and generate_client_actions () =
5446   generate_header CStyle LGPLv2plus;
5447
5448   pr "\
5449 #include <stdio.h>
5450 #include <stdlib.h>
5451 #include <stdint.h>
5452 #include <string.h>
5453 #include <inttypes.h>
5454
5455 #include \"guestfs.h\"
5456 #include \"guestfs-internal.h\"
5457 #include \"guestfs-internal-actions.h\"
5458 #include \"guestfs_protocol.h\"
5459
5460 #define error guestfs_error
5461 //#define perrorf guestfs_perrorf
5462 #define safe_malloc guestfs_safe_malloc
5463 #define safe_realloc guestfs_safe_realloc
5464 //#define safe_strdup guestfs_safe_strdup
5465 #define safe_memdup guestfs_safe_memdup
5466
5467 /* Check the return message from a call for validity. */
5468 static int
5469 check_reply_header (guestfs_h *g,
5470                     const struct guestfs_message_header *hdr,
5471                     unsigned int proc_nr, unsigned int serial)
5472 {
5473   if (hdr->prog != GUESTFS_PROGRAM) {
5474     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5475     return -1;
5476   }
5477   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5478     error (g, \"wrong protocol version (%%d/%%d)\",
5479            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5480     return -1;
5481   }
5482   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5483     error (g, \"unexpected message direction (%%d/%%d)\",
5484            hdr->direction, GUESTFS_DIRECTION_REPLY);
5485     return -1;
5486   }
5487   if (hdr->proc != proc_nr) {
5488     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5489     return -1;
5490   }
5491   if (hdr->serial != serial) {
5492     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5493     return -1;
5494   }
5495
5496   return 0;
5497 }
5498
5499 /* Check we are in the right state to run a high-level action. */
5500 static int
5501 check_state (guestfs_h *g, const char *caller)
5502 {
5503   if (!guestfs__is_ready (g)) {
5504     if (guestfs__is_config (g) || guestfs__is_launching (g))
5505       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5506         caller);
5507     else
5508       error (g, \"%%s called from the wrong state, %%d != READY\",
5509         caller, guestfs__get_state (g));
5510     return -1;
5511   }
5512   return 0;
5513 }
5514
5515 ";
5516
5517   (* Generate code to generate guestfish call traces. *)
5518   let trace_call shortname style =
5519     pr "  if (guestfs__get_trace (g)) {\n";
5520
5521     let needs_i =
5522       List.exists (function
5523                    | StringList _ | DeviceList _ -> true
5524                    | _ -> false) (snd style) in
5525     if needs_i then (
5526       pr "    int i;\n";
5527       pr "\n"
5528     );
5529
5530     pr "    printf (\"%s\");\n" shortname;
5531     List.iter (
5532       function
5533       | String n                        (* strings *)
5534       | Device n
5535       | Pathname n
5536       | Dev_or_Path n
5537       | FileIn n
5538       | FileOut n ->
5539           (* guestfish doesn't support string escaping, so neither do we *)
5540           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5541       | OptString n ->                  (* string option *)
5542           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5543           pr "    else printf (\" null\");\n"
5544       | StringList n
5545       | DeviceList n ->                 (* string list *)
5546           pr "    putchar (' ');\n";
5547           pr "    putchar ('\"');\n";
5548           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5549           pr "      if (i > 0) putchar (' ');\n";
5550           pr "      fputs (%s[i], stdout);\n" n;
5551           pr "    }\n";
5552           pr "    putchar ('\"');\n";
5553       | Bool n ->                       (* boolean *)
5554           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5555       | Int n ->                        (* int *)
5556           pr "    printf (\" %%d\", %s);\n" n
5557       | Int64 n ->
5558           pr "    printf (\" %%\" PRIi64, %s);\n" n
5559     ) (snd style);
5560     pr "    putchar ('\\n');\n";
5561     pr "  }\n";
5562     pr "\n";
5563   in
5564
5565   (* For non-daemon functions, generate a wrapper around each function. *)
5566   List.iter (
5567     fun (shortname, style, _, _, _, _, _) ->
5568       let name = "guestfs_" ^ shortname in
5569
5570       generate_prototype ~extern:false ~semicolon:false ~newline:true
5571         ~handle:"g" name style;
5572       pr "{\n";
5573       trace_call shortname style;
5574       pr "  return guestfs__%s " shortname;
5575       generate_c_call_args ~handle:"g" style;
5576       pr ";\n";
5577       pr "}\n";
5578       pr "\n"
5579   ) non_daemon_functions;
5580
5581   (* Client-side stubs for each function. *)
5582   List.iter (
5583     fun (shortname, style, _, _, _, _, _) ->
5584       let name = "guestfs_" ^ shortname in
5585
5586       (* Generate the action stub. *)
5587       generate_prototype ~extern:false ~semicolon:false ~newline:true
5588         ~handle:"g" name style;
5589
5590       let error_code =
5591         match fst style with
5592         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5593         | RConstString _ | RConstOptString _ ->
5594             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5595         | RString _ | RStringList _
5596         | RStruct _ | RStructList _
5597         | RHashtable _ | RBufferOut _ ->
5598             "NULL" in
5599
5600       pr "{\n";
5601
5602       (match snd style with
5603        | [] -> ()
5604        | _ -> pr "  struct %s_args args;\n" name
5605       );
5606
5607       pr "  guestfs_message_header hdr;\n";
5608       pr "  guestfs_message_error err;\n";
5609       let has_ret =
5610         match fst style with
5611         | RErr -> false
5612         | RConstString _ | RConstOptString _ ->
5613             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5614         | RInt _ | RInt64 _
5615         | RBool _ | RString _ | RStringList _
5616         | RStruct _ | RStructList _
5617         | RHashtable _ | RBufferOut _ ->
5618             pr "  struct %s_ret ret;\n" name;
5619             true in
5620
5621       pr "  int serial;\n";
5622       pr "  int r;\n";
5623       pr "\n";
5624       trace_call shortname style;
5625       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5626       pr "  guestfs___set_busy (g);\n";
5627       pr "\n";
5628
5629       (* Send the main header and arguments. *)
5630       (match snd style with
5631        | [] ->
5632            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5633              (String.uppercase shortname)
5634        | args ->
5635            List.iter (
5636              function
5637              | Pathname n | Device n | Dev_or_Path n | String n ->
5638                  pr "  args.%s = (char *) %s;\n" n n
5639              | OptString n ->
5640                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5641              | StringList n | DeviceList n ->
5642                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5643                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5644              | Bool n ->
5645                  pr "  args.%s = %s;\n" n n
5646              | Int n ->
5647                  pr "  args.%s = %s;\n" n n
5648              | Int64 n ->
5649                  pr "  args.%s = %s;\n" n n
5650              | FileIn _ | FileOut _ -> ()
5651            ) args;
5652            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5653              (String.uppercase shortname);
5654            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5655              name;
5656       );
5657       pr "  if (serial == -1) {\n";
5658       pr "    guestfs___end_busy (g);\n";
5659       pr "    return %s;\n" error_code;
5660       pr "  }\n";
5661       pr "\n";
5662
5663       (* Send any additional files (FileIn) requested. *)
5664       let need_read_reply_label = ref false in
5665       List.iter (
5666         function
5667         | FileIn n ->
5668             pr "  r = guestfs___send_file (g, %s);\n" n;
5669             pr "  if (r == -1) {\n";
5670             pr "    guestfs___end_busy (g);\n";
5671             pr "    return %s;\n" error_code;
5672             pr "  }\n";
5673             pr "  if (r == -2) /* daemon cancelled */\n";
5674             pr "    goto read_reply;\n";
5675             need_read_reply_label := true;
5676             pr "\n";
5677         | _ -> ()
5678       ) (snd style);
5679
5680       (* Wait for the reply from the remote end. *)
5681       if !need_read_reply_label then pr " read_reply:\n";
5682       pr "  memset (&hdr, 0, sizeof hdr);\n";
5683       pr "  memset (&err, 0, sizeof err);\n";
5684       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5685       pr "\n";
5686       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5687       if not has_ret then
5688         pr "NULL, NULL"
5689       else
5690         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5691       pr ");\n";
5692
5693       pr "  if (r == -1) {\n";
5694       pr "    guestfs___end_busy (g);\n";
5695       pr "    return %s;\n" error_code;
5696       pr "  }\n";
5697       pr "\n";
5698
5699       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5700         (String.uppercase shortname);
5701       pr "    guestfs___end_busy (g);\n";
5702       pr "    return %s;\n" error_code;
5703       pr "  }\n";
5704       pr "\n";
5705
5706       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5707       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5708       pr "    free (err.error_message);\n";
5709       pr "    guestfs___end_busy (g);\n";
5710       pr "    return %s;\n" error_code;
5711       pr "  }\n";
5712       pr "\n";
5713
5714       (* Expecting to receive further files (FileOut)? *)
5715       List.iter (
5716         function
5717         | FileOut n ->
5718             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5719             pr "    guestfs___end_busy (g);\n";
5720             pr "    return %s;\n" error_code;
5721             pr "  }\n";
5722             pr "\n";
5723         | _ -> ()
5724       ) (snd style);
5725
5726       pr "  guestfs___end_busy (g);\n";
5727
5728       (match fst style with
5729        | RErr -> pr "  return 0;\n"
5730        | RInt n | RInt64 n | RBool n ->
5731            pr "  return ret.%s;\n" n
5732        | RConstString _ | RConstOptString _ ->
5733            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5734        | RString n ->
5735            pr "  return ret.%s; /* caller will free */\n" n
5736        | RStringList n | RHashtable n ->
5737            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5738            pr "  ret.%s.%s_val =\n" n n;
5739            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5740            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5741              n n;
5742            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5743            pr "  return ret.%s.%s_val;\n" n n
5744        | RStruct (n, _) ->
5745            pr "  /* caller will free this */\n";
5746            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5747        | RStructList (n, _) ->
5748            pr "  /* caller will free this */\n";
5749            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5750        | RBufferOut n ->
5751            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5752            pr "   * _val might be NULL here.  To make the API saner for\n";
5753            pr "   * callers, we turn this case into a unique pointer (using\n";
5754            pr "   * malloc(1)).\n";
5755            pr "   */\n";
5756            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5757            pr "    *size_r = ret.%s.%s_len;\n" n n;
5758            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5759            pr "  } else {\n";
5760            pr "    free (ret.%s.%s_val);\n" n n;
5761            pr "    char *p = safe_malloc (g, 1);\n";
5762            pr "    *size_r = ret.%s.%s_len;\n" n n;
5763            pr "    return p;\n";
5764            pr "  }\n";
5765       );
5766
5767       pr "}\n\n"
5768   ) daemon_functions;
5769
5770   (* Functions to free structures. *)
5771   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5772   pr " * structure format is identical to the XDR format.  See note in\n";
5773   pr " * generator.ml.\n";
5774   pr " */\n";
5775   pr "\n";
5776
5777   List.iter (
5778     fun (typ, _) ->
5779       pr "void\n";
5780       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5781       pr "{\n";
5782       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5783       pr "  free (x);\n";
5784       pr "}\n";
5785       pr "\n";
5786
5787       pr "void\n";
5788       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5789       pr "{\n";
5790       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5791       pr "  free (x);\n";
5792       pr "}\n";
5793       pr "\n";
5794
5795   ) structs;
5796
5797 (* Generate daemon/actions.h. *)
5798 and generate_daemon_actions_h () =
5799   generate_header CStyle GPLv2plus;
5800
5801   pr "#include \"../src/guestfs_protocol.h\"\n";
5802   pr "\n";
5803
5804   List.iter (
5805     fun (name, style, _, _, _, _, _) ->
5806       generate_prototype
5807         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5808         name style;
5809   ) daemon_functions
5810
5811 (* Generate the linker script which controls the visibility of
5812  * symbols in the public ABI and ensures no other symbols get
5813  * exported accidentally.
5814  *)
5815 and generate_linker_script () =
5816   generate_header HashStyle GPLv2plus;
5817
5818   let globals = [
5819     "guestfs_create";
5820     "guestfs_close";
5821     "guestfs_get_error_handler";
5822     "guestfs_get_out_of_memory_handler";
5823     "guestfs_last_error";
5824     "guestfs_set_error_handler";
5825     "guestfs_set_launch_done_callback";
5826     "guestfs_set_log_message_callback";
5827     "guestfs_set_out_of_memory_handler";
5828     "guestfs_set_subprocess_quit_callback";
5829
5830     (* Unofficial parts of the API: the bindings code use these
5831      * functions, so it is useful to export them.
5832      *)
5833     "guestfs_safe_calloc";
5834     "guestfs_safe_malloc";
5835   ] in
5836   let functions =
5837     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5838       all_functions in
5839   let structs =
5840     List.concat (
5841       List.map (fun (typ, _) ->
5842                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5843         structs
5844     ) in
5845   let globals = List.sort compare (globals @ functions @ structs) in
5846
5847   pr "{\n";
5848   pr "    global:\n";
5849   List.iter (pr "        %s;\n") globals;
5850   pr "\n";
5851
5852   pr "    local:\n";
5853   pr "        *;\n";
5854   pr "};\n"
5855
5856 (* Generate the server-side stubs. *)
5857 and generate_daemon_actions () =
5858   generate_header CStyle GPLv2plus;
5859
5860   pr "#include <config.h>\n";
5861   pr "\n";
5862   pr "#include <stdio.h>\n";
5863   pr "#include <stdlib.h>\n";
5864   pr "#include <string.h>\n";
5865   pr "#include <inttypes.h>\n";
5866   pr "#include <rpc/types.h>\n";
5867   pr "#include <rpc/xdr.h>\n";
5868   pr "\n";
5869   pr "#include \"daemon.h\"\n";
5870   pr "#include \"c-ctype.h\"\n";
5871   pr "#include \"../src/guestfs_protocol.h\"\n";
5872   pr "#include \"actions.h\"\n";
5873   pr "\n";
5874
5875   List.iter (
5876     fun (name, style, _, _, _, _, _) ->
5877       (* Generate server-side stubs. *)
5878       pr "static void %s_stub (XDR *xdr_in)\n" name;
5879       pr "{\n";
5880       let error_code =
5881         match fst style with
5882         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5883         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5884         | RBool _ -> pr "  int r;\n"; "-1"
5885         | RConstString _ | RConstOptString _ ->
5886             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5887         | RString _ -> pr "  char *r;\n"; "NULL"
5888         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5889         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5890         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5891         | RBufferOut _ ->
5892             pr "  size_t size = 1;\n";
5893             pr "  char *r;\n";
5894             "NULL" in
5895
5896       (match snd style with
5897        | [] -> ()
5898        | args ->
5899            pr "  struct guestfs_%s_args args;\n" name;
5900            List.iter (
5901              function
5902              | Device n | Dev_or_Path n
5903              | Pathname n
5904              | String n -> ()
5905              | OptString n -> pr "  char *%s;\n" n
5906              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5907              | Bool n -> pr "  int %s;\n" n
5908              | Int n -> pr "  int %s;\n" n
5909              | Int64 n -> pr "  int64_t %s;\n" n
5910              | FileIn _ | FileOut _ -> ()
5911            ) args
5912       );
5913       pr "\n";
5914
5915       (match snd style with
5916        | [] -> ()
5917        | args ->
5918            pr "  memset (&args, 0, sizeof args);\n";
5919            pr "\n";
5920            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5921            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5922            pr "    return;\n";
5923            pr "  }\n";
5924            let pr_args n =
5925              pr "  char *%s = args.%s;\n" n n
5926            in
5927            let pr_list_handling_code n =
5928              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5929              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5930              pr "  if (%s == NULL) {\n" n;
5931              pr "    reply_with_perror (\"realloc\");\n";
5932              pr "    goto done;\n";
5933              pr "  }\n";
5934              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5935              pr "  args.%s.%s_val = %s;\n" n n n;
5936            in
5937            List.iter (
5938              function
5939              | Pathname n ->
5940                  pr_args n;
5941                  pr "  ABS_PATH (%s, goto done);\n" n;
5942              | Device n ->
5943                  pr_args n;
5944                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5945              | Dev_or_Path n ->
5946                  pr_args n;
5947                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5948              | String n -> pr_args n
5949              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5950              | StringList n ->
5951                  pr_list_handling_code n;
5952              | DeviceList n ->
5953                  pr_list_handling_code n;
5954                  pr "  /* Ensure that each is a device,\n";
5955                  pr "   * and perform device name translation. */\n";
5956                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5957                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5958                  pr "  }\n";
5959              | Bool n -> pr "  %s = args.%s;\n" n n
5960              | Int n -> pr "  %s = args.%s;\n" n n
5961              | Int64 n -> pr "  %s = args.%s;\n" n n
5962              | FileIn _ | FileOut _ -> ()
5963            ) args;
5964            pr "\n"
5965       );
5966
5967
5968       (* this is used at least for do_equal *)
5969       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5970         (* Emit NEED_ROOT just once, even when there are two or
5971            more Pathname args *)
5972         pr "  NEED_ROOT (goto done);\n";
5973       );
5974
5975       (* Don't want to call the impl with any FileIn or FileOut
5976        * parameters, since these go "outside" the RPC protocol.
5977        *)
5978       let args' =
5979         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5980           (snd style) in
5981       pr "  r = do_%s " name;
5982       generate_c_call_args (fst style, args');
5983       pr ";\n";
5984
5985       (match fst style with
5986        | RErr | RInt _ | RInt64 _ | RBool _
5987        | RConstString _ | RConstOptString _
5988        | RString _ | RStringList _ | RHashtable _
5989        | RStruct (_, _) | RStructList (_, _) ->
5990            pr "  if (r == %s)\n" error_code;
5991            pr "    /* do_%s has already called reply_with_error */\n" name;
5992            pr "    goto done;\n";
5993            pr "\n"
5994        | RBufferOut _ ->
5995            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5996            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5997            pr "   */\n";
5998            pr "  if (size == 1 && r == %s)\n" error_code;
5999            pr "    /* do_%s has already called reply_with_error */\n" name;
6000            pr "    goto done;\n";
6001            pr "\n"
6002       );
6003
6004       (* If there are any FileOut parameters, then the impl must
6005        * send its own reply.
6006        *)
6007       let no_reply =
6008         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6009       if no_reply then
6010         pr "  /* do_%s has already sent a reply */\n" name
6011       else (
6012         match fst style with
6013         | RErr -> pr "  reply (NULL, NULL);\n"
6014         | RInt n | RInt64 n | RBool n ->
6015             pr "  struct guestfs_%s_ret ret;\n" name;
6016             pr "  ret.%s = r;\n" n;
6017             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6018               name
6019         | RConstString _ | RConstOptString _ ->
6020             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6021         | RString n ->
6022             pr "  struct guestfs_%s_ret ret;\n" name;
6023             pr "  ret.%s = r;\n" n;
6024             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6025               name;
6026             pr "  free (r);\n"
6027         | RStringList n | RHashtable n ->
6028             pr "  struct guestfs_%s_ret ret;\n" name;
6029             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6030             pr "  ret.%s.%s_val = r;\n" n n;
6031             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6032               name;
6033             pr "  free_strings (r);\n"
6034         | RStruct (n, _) ->
6035             pr "  struct guestfs_%s_ret ret;\n" name;
6036             pr "  ret.%s = *r;\n" n;
6037             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6038               name;
6039             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6040               name
6041         | RStructList (n, _) ->
6042             pr "  struct guestfs_%s_ret ret;\n" name;
6043             pr "  ret.%s = *r;\n" n;
6044             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6045               name;
6046             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6047               name
6048         | RBufferOut n ->
6049             pr "  struct guestfs_%s_ret ret;\n" name;
6050             pr "  ret.%s.%s_val = r;\n" n n;
6051             pr "  ret.%s.%s_len = size;\n" n n;
6052             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6053               name;
6054             pr "  free (r);\n"
6055       );
6056
6057       (* Free the args. *)
6058       (match snd style with
6059        | [] ->
6060            pr "done: ;\n";
6061        | _ ->
6062            pr "done:\n";
6063            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6064              name
6065       );
6066
6067       pr "}\n\n";
6068   ) daemon_functions;
6069
6070   (* Dispatch function. *)
6071   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6072   pr "{\n";
6073   pr "  switch (proc_nr) {\n";
6074
6075   List.iter (
6076     fun (name, style, _, _, _, _, _) ->
6077       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6078       pr "      %s_stub (xdr_in);\n" name;
6079       pr "      break;\n"
6080   ) daemon_functions;
6081
6082   pr "    default:\n";
6083   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";
6084   pr "  }\n";
6085   pr "}\n";
6086   pr "\n";
6087
6088   (* LVM columns and tokenization functions. *)
6089   (* XXX This generates crap code.  We should rethink how we
6090    * do this parsing.
6091    *)
6092   List.iter (
6093     function
6094     | typ, cols ->
6095         pr "static const char *lvm_%s_cols = \"%s\";\n"
6096           typ (String.concat "," (List.map fst cols));
6097         pr "\n";
6098
6099         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6100         pr "{\n";
6101         pr "  char *tok, *p, *next;\n";
6102         pr "  int i, j;\n";
6103         pr "\n";
6104         (*
6105           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6106           pr "\n";
6107         *)
6108         pr "  if (!str) {\n";
6109         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6110         pr "    return -1;\n";
6111         pr "  }\n";
6112         pr "  if (!*str || c_isspace (*str)) {\n";
6113         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6114         pr "    return -1;\n";
6115         pr "  }\n";
6116         pr "  tok = str;\n";
6117         List.iter (
6118           fun (name, coltype) ->
6119             pr "  if (!tok) {\n";
6120             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6121             pr "    return -1;\n";
6122             pr "  }\n";
6123             pr "  p = strchrnul (tok, ',');\n";
6124             pr "  if (*p) next = p+1; else next = NULL;\n";
6125             pr "  *p = '\\0';\n";
6126             (match coltype with
6127              | FString ->
6128                  pr "  r->%s = strdup (tok);\n" name;
6129                  pr "  if (r->%s == NULL) {\n" name;
6130                  pr "    perror (\"strdup\");\n";
6131                  pr "    return -1;\n";
6132                  pr "  }\n"
6133              | FUUID ->
6134                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6135                  pr "    if (tok[j] == '\\0') {\n";
6136                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6137                  pr "      return -1;\n";
6138                  pr "    } else if (tok[j] != '-')\n";
6139                  pr "      r->%s[i++] = tok[j];\n" name;
6140                  pr "  }\n";
6141              | FBytes ->
6142                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6143                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6144                  pr "    return -1;\n";
6145                  pr "  }\n";
6146              | FInt64 ->
6147                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6148                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6149                  pr "    return -1;\n";
6150                  pr "  }\n";
6151              | FOptPercent ->
6152                  pr "  if (tok[0] == '\\0')\n";
6153                  pr "    r->%s = -1;\n" name;
6154                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6155                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6156                  pr "    return -1;\n";
6157                  pr "  }\n";
6158              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6159                  assert false (* can never be an LVM column *)
6160             );
6161             pr "  tok = next;\n";
6162         ) cols;
6163
6164         pr "  if (tok != NULL) {\n";
6165         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6166         pr "    return -1;\n";
6167         pr "  }\n";
6168         pr "  return 0;\n";
6169         pr "}\n";
6170         pr "\n";
6171
6172         pr "guestfs_int_lvm_%s_list *\n" typ;
6173         pr "parse_command_line_%ss (void)\n" typ;
6174         pr "{\n";
6175         pr "  char *out, *err;\n";
6176         pr "  char *p, *pend;\n";
6177         pr "  int r, i;\n";
6178         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6179         pr "  void *newp;\n";
6180         pr "\n";
6181         pr "  ret = malloc (sizeof *ret);\n";
6182         pr "  if (!ret) {\n";
6183         pr "    reply_with_perror (\"malloc\");\n";
6184         pr "    return NULL;\n";
6185         pr "  }\n";
6186         pr "\n";
6187         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6188         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6189         pr "\n";
6190         pr "  r = command (&out, &err,\n";
6191         pr "           \"lvm\", \"%ss\",\n" typ;
6192         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6193         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6194         pr "  if (r == -1) {\n";
6195         pr "    reply_with_error (\"%%s\", err);\n";
6196         pr "    free (out);\n";
6197         pr "    free (err);\n";
6198         pr "    free (ret);\n";
6199         pr "    return NULL;\n";
6200         pr "  }\n";
6201         pr "\n";
6202         pr "  free (err);\n";
6203         pr "\n";
6204         pr "  /* Tokenize each line of the output. */\n";
6205         pr "  p = out;\n";
6206         pr "  i = 0;\n";
6207         pr "  while (p) {\n";
6208         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6209         pr "    if (pend) {\n";
6210         pr "      *pend = '\\0';\n";
6211         pr "      pend++;\n";
6212         pr "    }\n";
6213         pr "\n";
6214         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6215         pr "      p++;\n";
6216         pr "\n";
6217         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6218         pr "      p = pend;\n";
6219         pr "      continue;\n";
6220         pr "    }\n";
6221         pr "\n";
6222         pr "    /* Allocate some space to store this next entry. */\n";
6223         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6224         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6225         pr "    if (newp == NULL) {\n";
6226         pr "      reply_with_perror (\"realloc\");\n";
6227         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6228         pr "      free (ret);\n";
6229         pr "      free (out);\n";
6230         pr "      return NULL;\n";
6231         pr "    }\n";
6232         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6233         pr "\n";
6234         pr "    /* Tokenize the next entry. */\n";
6235         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6236         pr "    if (r == -1) {\n";
6237         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6238         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6239         pr "      free (ret);\n";
6240         pr "      free (out);\n";
6241         pr "      return NULL;\n";
6242         pr "    }\n";
6243         pr "\n";
6244         pr "    ++i;\n";
6245         pr "    p = pend;\n";
6246         pr "  }\n";
6247         pr "\n";
6248         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6249         pr "\n";
6250         pr "  free (out);\n";
6251         pr "  return ret;\n";
6252         pr "}\n"
6253
6254   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6255
6256 (* Generate a list of function names, for debugging in the daemon.. *)
6257 and generate_daemon_names () =
6258   generate_header CStyle GPLv2plus;
6259
6260   pr "#include <config.h>\n";
6261   pr "\n";
6262   pr "#include \"daemon.h\"\n";
6263   pr "\n";
6264
6265   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6266   pr "const char *function_names[] = {\n";
6267   List.iter (
6268     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6269   ) daemon_functions;
6270   pr "};\n";
6271
6272 (* Generate the optional groups for the daemon to implement
6273  * guestfs_available.
6274  *)
6275 and generate_daemon_optgroups_c () =
6276   generate_header CStyle GPLv2plus;
6277
6278   pr "#include <config.h>\n";
6279   pr "\n";
6280   pr "#include \"daemon.h\"\n";
6281   pr "#include \"optgroups.h\"\n";
6282   pr "\n";
6283
6284   pr "struct optgroup optgroups[] = {\n";
6285   List.iter (
6286     fun (group, _) ->
6287       pr "  { \"%s\", optgroup_%s_available },\n" group group
6288   ) optgroups;
6289   pr "  { NULL, NULL }\n";
6290   pr "};\n"
6291
6292 and generate_daemon_optgroups_h () =
6293   generate_header CStyle GPLv2plus;
6294
6295   List.iter (
6296     fun (group, _) ->
6297       pr "extern int optgroup_%s_available (void);\n" group
6298   ) optgroups
6299
6300 (* Generate the tests. *)
6301 and generate_tests () =
6302   generate_header CStyle GPLv2plus;
6303
6304   pr "\
6305 #include <stdio.h>
6306 #include <stdlib.h>
6307 #include <string.h>
6308 #include <unistd.h>
6309 #include <sys/types.h>
6310 #include <fcntl.h>
6311
6312 #include \"guestfs.h\"
6313 #include \"guestfs-internal.h\"
6314
6315 static guestfs_h *g;
6316 static int suppress_error = 0;
6317
6318 static void print_error (guestfs_h *g, void *data, const char *msg)
6319 {
6320   if (!suppress_error)
6321     fprintf (stderr, \"%%s\\n\", msg);
6322 }
6323
6324 /* FIXME: nearly identical code appears in fish.c */
6325 static void print_strings (char *const *argv)
6326 {
6327   int argc;
6328
6329   for (argc = 0; argv[argc] != NULL; ++argc)
6330     printf (\"\\t%%s\\n\", argv[argc]);
6331 }
6332
6333 /*
6334 static void print_table (char const *const *argv)
6335 {
6336   int i;
6337
6338   for (i = 0; argv[i] != NULL; i += 2)
6339     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6340 }
6341 */
6342
6343 ";
6344
6345   (* Generate a list of commands which are not tested anywhere. *)
6346   pr "static void no_test_warnings (void)\n";
6347   pr "{\n";
6348
6349   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6350   List.iter (
6351     fun (_, _, _, _, tests, _, _) ->
6352       let tests = filter_map (
6353         function
6354         | (_, (Always|If _|Unless _), test) -> Some test
6355         | (_, Disabled, _) -> None
6356       ) tests in
6357       let seq = List.concat (List.map seq_of_test tests) in
6358       let cmds_tested = List.map List.hd seq in
6359       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6360   ) all_functions;
6361
6362   List.iter (
6363     fun (name, _, _, _, _, _, _) ->
6364       if not (Hashtbl.mem hash name) then
6365         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6366   ) all_functions;
6367
6368   pr "}\n";
6369   pr "\n";
6370
6371   (* Generate the actual tests.  Note that we generate the tests
6372    * in reverse order, deliberately, so that (in general) the
6373    * newest tests run first.  This makes it quicker and easier to
6374    * debug them.
6375    *)
6376   let test_names =
6377     List.map (
6378       fun (name, _, _, flags, tests, _, _) ->
6379         mapi (generate_one_test name flags) tests
6380     ) (List.rev all_functions) in
6381   let test_names = List.concat test_names in
6382   let nr_tests = List.length test_names in
6383
6384   pr "\
6385 int main (int argc, char *argv[])
6386 {
6387   char c = 0;
6388   unsigned long int n_failed = 0;
6389   const char *filename;
6390   int fd;
6391   int nr_tests, test_num = 0;
6392
6393   setbuf (stdout, NULL);
6394
6395   no_test_warnings ();
6396
6397   g = guestfs_create ();
6398   if (g == NULL) {
6399     printf (\"guestfs_create FAILED\\n\");
6400     exit (EXIT_FAILURE);
6401   }
6402
6403   guestfs_set_error_handler (g, print_error, NULL);
6404
6405   guestfs_set_path (g, \"../appliance\");
6406
6407   filename = \"test1.img\";
6408   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6409   if (fd == -1) {
6410     perror (filename);
6411     exit (EXIT_FAILURE);
6412   }
6413   if (lseek (fd, %d, SEEK_SET) == -1) {
6414     perror (\"lseek\");
6415     close (fd);
6416     unlink (filename);
6417     exit (EXIT_FAILURE);
6418   }
6419   if (write (fd, &c, 1) == -1) {
6420     perror (\"write\");
6421     close (fd);
6422     unlink (filename);
6423     exit (EXIT_FAILURE);
6424   }
6425   if (close (fd) == -1) {
6426     perror (filename);
6427     unlink (filename);
6428     exit (EXIT_FAILURE);
6429   }
6430   if (guestfs_add_drive (g, filename) == -1) {
6431     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6432     exit (EXIT_FAILURE);
6433   }
6434
6435   filename = \"test2.img\";
6436   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6437   if (fd == -1) {
6438     perror (filename);
6439     exit (EXIT_FAILURE);
6440   }
6441   if (lseek (fd, %d, SEEK_SET) == -1) {
6442     perror (\"lseek\");
6443     close (fd);
6444     unlink (filename);
6445     exit (EXIT_FAILURE);
6446   }
6447   if (write (fd, &c, 1) == -1) {
6448     perror (\"write\");
6449     close (fd);
6450     unlink (filename);
6451     exit (EXIT_FAILURE);
6452   }
6453   if (close (fd) == -1) {
6454     perror (filename);
6455     unlink (filename);
6456     exit (EXIT_FAILURE);
6457   }
6458   if (guestfs_add_drive (g, filename) == -1) {
6459     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6460     exit (EXIT_FAILURE);
6461   }
6462
6463   filename = \"test3.img\";
6464   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6465   if (fd == -1) {
6466     perror (filename);
6467     exit (EXIT_FAILURE);
6468   }
6469   if (lseek (fd, %d, SEEK_SET) == -1) {
6470     perror (\"lseek\");
6471     close (fd);
6472     unlink (filename);
6473     exit (EXIT_FAILURE);
6474   }
6475   if (write (fd, &c, 1) == -1) {
6476     perror (\"write\");
6477     close (fd);
6478     unlink (filename);
6479     exit (EXIT_FAILURE);
6480   }
6481   if (close (fd) == -1) {
6482     perror (filename);
6483     unlink (filename);
6484     exit (EXIT_FAILURE);
6485   }
6486   if (guestfs_add_drive (g, filename) == -1) {
6487     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6488     exit (EXIT_FAILURE);
6489   }
6490
6491   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6492     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6493     exit (EXIT_FAILURE);
6494   }
6495
6496   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6497   alarm (600);
6498
6499   if (guestfs_launch (g) == -1) {
6500     printf (\"guestfs_launch FAILED\\n\");
6501     exit (EXIT_FAILURE);
6502   }
6503
6504   /* Cancel previous alarm. */
6505   alarm (0);
6506
6507   nr_tests = %d;
6508
6509 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6510
6511   iteri (
6512     fun i test_name ->
6513       pr "  test_num++;\n";
6514       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6515       pr "  if (%s () == -1) {\n" test_name;
6516       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6517       pr "    n_failed++;\n";
6518       pr "  }\n";
6519   ) test_names;
6520   pr "\n";
6521
6522   pr "  guestfs_close (g);\n";
6523   pr "  unlink (\"test1.img\");\n";
6524   pr "  unlink (\"test2.img\");\n";
6525   pr "  unlink (\"test3.img\");\n";
6526   pr "\n";
6527
6528   pr "  if (n_failed > 0) {\n";
6529   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6530   pr "    exit (EXIT_FAILURE);\n";
6531   pr "  }\n";
6532   pr "\n";
6533
6534   pr "  exit (EXIT_SUCCESS);\n";
6535   pr "}\n"
6536
6537 and generate_one_test name flags i (init, prereq, test) =
6538   let test_name = sprintf "test_%s_%d" name i in
6539
6540   pr "\
6541 static int %s_skip (void)
6542 {
6543   const char *str;
6544
6545   str = getenv (\"TEST_ONLY\");
6546   if (str)
6547     return strstr (str, \"%s\") == NULL;
6548   str = getenv (\"SKIP_%s\");
6549   if (str && STREQ (str, \"1\")) return 1;
6550   str = getenv (\"SKIP_TEST_%s\");
6551   if (str && STREQ (str, \"1\")) return 1;
6552   return 0;
6553 }
6554
6555 " test_name name (String.uppercase test_name) (String.uppercase name);
6556
6557   (match prereq with
6558    | Disabled | Always -> ()
6559    | If code | Unless code ->
6560        pr "static int %s_prereq (void)\n" test_name;
6561        pr "{\n";
6562        pr "  %s\n" code;
6563        pr "}\n";
6564        pr "\n";
6565   );
6566
6567   pr "\
6568 static int %s (void)
6569 {
6570   if (%s_skip ()) {
6571     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6572     return 0;
6573   }
6574
6575 " test_name test_name test_name;
6576
6577   (* Optional functions should only be tested if the relevant
6578    * support is available in the daemon.
6579    *)
6580   List.iter (
6581     function
6582     | Optional group ->
6583         pr "  {\n";
6584         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6585         pr "    int r;\n";
6586         pr "    suppress_error = 1;\n";
6587         pr "    r = guestfs_available (g, (char **) groups);\n";
6588         pr "    suppress_error = 0;\n";
6589         pr "    if (r == -1) {\n";
6590         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6591         pr "      return 0;\n";
6592         pr "    }\n";
6593         pr "  }\n";
6594     | _ -> ()
6595   ) flags;
6596
6597   (match prereq with
6598    | Disabled ->
6599        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6600    | If _ ->
6601        pr "  if (! %s_prereq ()) {\n" test_name;
6602        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6603        pr "    return 0;\n";
6604        pr "  }\n";
6605        pr "\n";
6606        generate_one_test_body name i test_name init test;
6607    | Unless _ ->
6608        pr "  if (%s_prereq ()) {\n" test_name;
6609        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6610        pr "    return 0;\n";
6611        pr "  }\n";
6612        pr "\n";
6613        generate_one_test_body name i test_name init test;
6614    | Always ->
6615        generate_one_test_body name i test_name init test
6616   );
6617
6618   pr "  return 0;\n";
6619   pr "}\n";
6620   pr "\n";
6621   test_name
6622
6623 and generate_one_test_body name i test_name init test =
6624   (match init with
6625    | InitNone (* XXX at some point, InitNone and InitEmpty became
6626                * folded together as the same thing.  Really we should
6627                * make InitNone do nothing at all, but the tests may
6628                * need to be checked to make sure this is OK.
6629                *)
6630    | InitEmpty ->
6631        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6632        List.iter (generate_test_command_call test_name)
6633          [["blockdev_setrw"; "/dev/sda"];
6634           ["umount_all"];
6635           ["lvm_remove_all"]]
6636    | InitPartition ->
6637        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6638        List.iter (generate_test_command_call test_name)
6639          [["blockdev_setrw"; "/dev/sda"];
6640           ["umount_all"];
6641           ["lvm_remove_all"];
6642           ["part_disk"; "/dev/sda"; "mbr"]]
6643    | InitBasicFS ->
6644        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6645        List.iter (generate_test_command_call test_name)
6646          [["blockdev_setrw"; "/dev/sda"];
6647           ["umount_all"];
6648           ["lvm_remove_all"];
6649           ["part_disk"; "/dev/sda"; "mbr"];
6650           ["mkfs"; "ext2"; "/dev/sda1"];
6651           ["mount_options"; ""; "/dev/sda1"; "/"]]
6652    | InitBasicFSonLVM ->
6653        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6654          test_name;
6655        List.iter (generate_test_command_call test_name)
6656          [["blockdev_setrw"; "/dev/sda"];
6657           ["umount_all"];
6658           ["lvm_remove_all"];
6659           ["part_disk"; "/dev/sda"; "mbr"];
6660           ["pvcreate"; "/dev/sda1"];
6661           ["vgcreate"; "VG"; "/dev/sda1"];
6662           ["lvcreate"; "LV"; "VG"; "8"];
6663           ["mkfs"; "ext2"; "/dev/VG/LV"];
6664           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6665    | InitISOFS ->
6666        pr "  /* InitISOFS for %s */\n" test_name;
6667        List.iter (generate_test_command_call test_name)
6668          [["blockdev_setrw"; "/dev/sda"];
6669           ["umount_all"];
6670           ["lvm_remove_all"];
6671           ["mount_ro"; "/dev/sdd"; "/"]]
6672   );
6673
6674   let get_seq_last = function
6675     | [] ->
6676         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6677           test_name
6678     | seq ->
6679         let seq = List.rev seq in
6680         List.rev (List.tl seq), List.hd seq
6681   in
6682
6683   match test with
6684   | TestRun seq ->
6685       pr "  /* TestRun for %s (%d) */\n" name i;
6686       List.iter (generate_test_command_call test_name) seq
6687   | TestOutput (seq, expected) ->
6688       pr "  /* TestOutput for %s (%d) */\n" name i;
6689       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6690       let seq, last = get_seq_last seq in
6691       let test () =
6692         pr "    if (STRNEQ (r, expected)) {\n";
6693         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6694         pr "      return -1;\n";
6695         pr "    }\n"
6696       in
6697       List.iter (generate_test_command_call test_name) seq;
6698       generate_test_command_call ~test test_name last
6699   | TestOutputList (seq, expected) ->
6700       pr "  /* TestOutputList for %s (%d) */\n" name i;
6701       let seq, last = get_seq_last seq in
6702       let test () =
6703         iteri (
6704           fun i str ->
6705             pr "    if (!r[%d]) {\n" i;
6706             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6707             pr "      print_strings (r);\n";
6708             pr "      return -1;\n";
6709             pr "    }\n";
6710             pr "    {\n";
6711             pr "      const char *expected = \"%s\";\n" (c_quote str);
6712             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6713             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6714             pr "        return -1;\n";
6715             pr "      }\n";
6716             pr "    }\n"
6717         ) expected;
6718         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6719         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6720           test_name;
6721         pr "      print_strings (r);\n";
6722         pr "      return -1;\n";
6723         pr "    }\n"
6724       in
6725       List.iter (generate_test_command_call test_name) seq;
6726       generate_test_command_call ~test test_name last
6727   | TestOutputListOfDevices (seq, expected) ->
6728       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6729       let seq, last = get_seq_last seq in
6730       let test () =
6731         iteri (
6732           fun i str ->
6733             pr "    if (!r[%d]) {\n" i;
6734             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6735             pr "      print_strings (r);\n";
6736             pr "      return -1;\n";
6737             pr "    }\n";
6738             pr "    {\n";
6739             pr "      const char *expected = \"%s\";\n" (c_quote str);
6740             pr "      r[%d][5] = 's';\n" i;
6741             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6742             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6743             pr "        return -1;\n";
6744             pr "      }\n";
6745             pr "    }\n"
6746         ) expected;
6747         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6748         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6749           test_name;
6750         pr "      print_strings (r);\n";
6751         pr "      return -1;\n";
6752         pr "    }\n"
6753       in
6754       List.iter (generate_test_command_call test_name) seq;
6755       generate_test_command_call ~test test_name last
6756   | TestOutputInt (seq, expected) ->
6757       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6758       let seq, last = get_seq_last seq in
6759       let test () =
6760         pr "    if (r != %d) {\n" expected;
6761         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6762           test_name expected;
6763         pr "               (int) r);\n";
6764         pr "      return -1;\n";
6765         pr "    }\n"
6766       in
6767       List.iter (generate_test_command_call test_name) seq;
6768       generate_test_command_call ~test test_name last
6769   | TestOutputIntOp (seq, op, expected) ->
6770       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6771       let seq, last = get_seq_last seq in
6772       let test () =
6773         pr "    if (! (r %s %d)) {\n" op expected;
6774         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6775           test_name op expected;
6776         pr "               (int) r);\n";
6777         pr "      return -1;\n";
6778         pr "    }\n"
6779       in
6780       List.iter (generate_test_command_call test_name) seq;
6781       generate_test_command_call ~test test_name last
6782   | TestOutputTrue seq ->
6783       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6784       let seq, last = get_seq_last seq in
6785       let test () =
6786         pr "    if (!r) {\n";
6787         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6788           test_name;
6789         pr "      return -1;\n";
6790         pr "    }\n"
6791       in
6792       List.iter (generate_test_command_call test_name) seq;
6793       generate_test_command_call ~test test_name last
6794   | TestOutputFalse seq ->
6795       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6796       let seq, last = get_seq_last seq in
6797       let test () =
6798         pr "    if (r) {\n";
6799         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6800           test_name;
6801         pr "      return -1;\n";
6802         pr "    }\n"
6803       in
6804       List.iter (generate_test_command_call test_name) seq;
6805       generate_test_command_call ~test test_name last
6806   | TestOutputLength (seq, expected) ->
6807       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6808       let seq, last = get_seq_last seq in
6809       let test () =
6810         pr "    int j;\n";
6811         pr "    for (j = 0; j < %d; ++j)\n" expected;
6812         pr "      if (r[j] == NULL) {\n";
6813         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6814           test_name;
6815         pr "        print_strings (r);\n";
6816         pr "        return -1;\n";
6817         pr "      }\n";
6818         pr "    if (r[j] != NULL) {\n";
6819         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6820           test_name;
6821         pr "      print_strings (r);\n";
6822         pr "      return -1;\n";
6823         pr "    }\n"
6824       in
6825       List.iter (generate_test_command_call test_name) seq;
6826       generate_test_command_call ~test test_name last
6827   | TestOutputBuffer (seq, expected) ->
6828       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6829       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6830       let seq, last = get_seq_last seq in
6831       let len = String.length expected in
6832       let test () =
6833         pr "    if (size != %d) {\n" len;
6834         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6835         pr "      return -1;\n";
6836         pr "    }\n";
6837         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6838         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6839         pr "      return -1;\n";
6840         pr "    }\n"
6841       in
6842       List.iter (generate_test_command_call test_name) seq;
6843       generate_test_command_call ~test test_name last
6844   | TestOutputStruct (seq, checks) ->
6845       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6846       let seq, last = get_seq_last seq in
6847       let test () =
6848         List.iter (
6849           function
6850           | CompareWithInt (field, expected) ->
6851               pr "    if (r->%s != %d) {\n" field expected;
6852               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6853                 test_name field expected;
6854               pr "               (int) r->%s);\n" field;
6855               pr "      return -1;\n";
6856               pr "    }\n"
6857           | CompareWithIntOp (field, op, expected) ->
6858               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6859               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6860                 test_name field op expected;
6861               pr "               (int) r->%s);\n" field;
6862               pr "      return -1;\n";
6863               pr "    }\n"
6864           | CompareWithString (field, expected) ->
6865               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6866               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6867                 test_name field expected;
6868               pr "               r->%s);\n" field;
6869               pr "      return -1;\n";
6870               pr "    }\n"
6871           | CompareFieldsIntEq (field1, field2) ->
6872               pr "    if (r->%s != r->%s) {\n" field1 field2;
6873               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6874                 test_name field1 field2;
6875               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6876               pr "      return -1;\n";
6877               pr "    }\n"
6878           | CompareFieldsStrEq (field1, field2) ->
6879               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6880               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6881                 test_name field1 field2;
6882               pr "               r->%s, r->%s);\n" field1 field2;
6883               pr "      return -1;\n";
6884               pr "    }\n"
6885         ) checks
6886       in
6887       List.iter (generate_test_command_call test_name) seq;
6888       generate_test_command_call ~test test_name last
6889   | TestLastFail seq ->
6890       pr "  /* TestLastFail for %s (%d) */\n" name i;
6891       let seq, last = get_seq_last seq in
6892       List.iter (generate_test_command_call test_name) seq;
6893       generate_test_command_call test_name ~expect_error:true last
6894
6895 (* Generate the code to run a command, leaving the result in 'r'.
6896  * If you expect to get an error then you should set expect_error:true.
6897  *)
6898 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6899   match cmd with
6900   | [] -> assert false
6901   | name :: args ->
6902       (* Look up the command to find out what args/ret it has. *)
6903       let style =
6904         try
6905           let _, style, _, _, _, _, _ =
6906             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6907           style
6908         with Not_found ->
6909           failwithf "%s: in test, command %s was not found" test_name name in
6910
6911       if List.length (snd style) <> List.length args then
6912         failwithf "%s: in test, wrong number of args given to %s"
6913           test_name name;
6914
6915       pr "  {\n";
6916
6917       List.iter (
6918         function
6919         | OptString n, "NULL" -> ()
6920         | Pathname n, arg
6921         | Device n, arg
6922         | Dev_or_Path n, arg
6923         | String n, arg
6924         | OptString n, arg ->
6925             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6926         | Int _, _
6927         | Int64 _, _
6928         | Bool _, _
6929         | FileIn _, _ | FileOut _, _ -> ()
6930         | StringList n, "" | DeviceList n, "" ->
6931             pr "    const char *const %s[1] = { NULL };\n" n
6932         | StringList n, arg | DeviceList n, arg ->
6933             let strs = string_split " " arg in
6934             iteri (
6935               fun i str ->
6936                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6937             ) strs;
6938             pr "    const char *const %s[] = {\n" n;
6939             iteri (
6940               fun i _ -> pr "      %s_%d,\n" n i
6941             ) strs;
6942             pr "      NULL\n";
6943             pr "    };\n";
6944       ) (List.combine (snd style) args);
6945
6946       let error_code =
6947         match fst style with
6948         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6949         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6950         | RConstString _ | RConstOptString _ ->
6951             pr "    const char *r;\n"; "NULL"
6952         | RString _ -> pr "    char *r;\n"; "NULL"
6953         | RStringList _ | RHashtable _ ->
6954             pr "    char **r;\n";
6955             pr "    int i;\n";
6956             "NULL"
6957         | RStruct (_, typ) ->
6958             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6959         | RStructList (_, typ) ->
6960             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6961         | RBufferOut _ ->
6962             pr "    char *r;\n";
6963             pr "    size_t size;\n";
6964             "NULL" in
6965
6966       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6967       pr "    r = guestfs_%s (g" name;
6968
6969       (* Generate the parameters. *)
6970       List.iter (
6971         function
6972         | OptString _, "NULL" -> pr ", NULL"
6973         | Pathname n, _
6974         | Device n, _ | Dev_or_Path n, _
6975         | String n, _
6976         | OptString n, _ ->
6977             pr ", %s" n
6978         | FileIn _, arg | FileOut _, arg ->
6979             pr ", \"%s\"" (c_quote arg)
6980         | StringList n, _ | DeviceList n, _ ->
6981             pr ", (char **) %s" n
6982         | Int _, arg ->
6983             let i =
6984               try int_of_string arg
6985               with Failure "int_of_string" ->
6986                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6987             pr ", %d" i
6988         | Int64 _, arg ->
6989             let i =
6990               try Int64.of_string arg
6991               with Failure "int_of_string" ->
6992                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6993             pr ", %Ld" i
6994         | Bool _, arg ->
6995             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6996       ) (List.combine (snd style) args);
6997
6998       (match fst style with
6999        | RBufferOut _ -> pr ", &size"
7000        | _ -> ()
7001       );
7002
7003       pr ");\n";
7004
7005       if not expect_error then
7006         pr "    if (r == %s)\n" error_code
7007       else
7008         pr "    if (r != %s)\n" error_code;
7009       pr "      return -1;\n";
7010
7011       (* Insert the test code. *)
7012       (match test with
7013        | None -> ()
7014        | Some f -> f ()
7015       );
7016
7017       (match fst style with
7018        | RErr | RInt _ | RInt64 _ | RBool _
7019        | RConstString _ | RConstOptString _ -> ()
7020        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7021        | RStringList _ | RHashtable _ ->
7022            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7023            pr "      free (r[i]);\n";
7024            pr "    free (r);\n"
7025        | RStruct (_, typ) ->
7026            pr "    guestfs_free_%s (r);\n" typ
7027        | RStructList (_, typ) ->
7028            pr "    guestfs_free_%s_list (r);\n" typ
7029       );
7030
7031       pr "  }\n"
7032
7033 and c_quote str =
7034   let str = replace_str str "\r" "\\r" in
7035   let str = replace_str str "\n" "\\n" in
7036   let str = replace_str str "\t" "\\t" in
7037   let str = replace_str str "\000" "\\0" in
7038   str
7039
7040 (* Generate a lot of different functions for guestfish. *)
7041 and generate_fish_cmds () =
7042   generate_header CStyle GPLv2plus;
7043
7044   let all_functions =
7045     List.filter (
7046       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7047     ) all_functions in
7048   let all_functions_sorted =
7049     List.filter (
7050       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7051     ) all_functions_sorted in
7052
7053   pr "#include <config.h>\n";
7054   pr "\n";
7055   pr "#include <stdio.h>\n";
7056   pr "#include <stdlib.h>\n";
7057   pr "#include <string.h>\n";
7058   pr "#include <inttypes.h>\n";
7059   pr "\n";
7060   pr "#include <guestfs.h>\n";
7061   pr "#include \"c-ctype.h\"\n";
7062   pr "#include \"full-write.h\"\n";
7063   pr "#include \"xstrtol.h\"\n";
7064   pr "#include \"fish.h\"\n";
7065   pr "\n";
7066
7067   (* list_commands function, which implements guestfish -h *)
7068   pr "void list_commands (void)\n";
7069   pr "{\n";
7070   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7071   pr "  list_builtin_commands ();\n";
7072   List.iter (
7073     fun (name, _, _, flags, _, shortdesc, _) ->
7074       let name = replace_char name '_' '-' in
7075       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7076         name shortdesc
7077   ) all_functions_sorted;
7078   pr "  printf (\"    %%s\\n\",";
7079   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7080   pr "}\n";
7081   pr "\n";
7082
7083   (* display_command function, which implements guestfish -h cmd *)
7084   pr "void display_command (const char *cmd)\n";
7085   pr "{\n";
7086   List.iter (
7087     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7088       let name2 = replace_char name '_' '-' in
7089       let alias =
7090         try find_map (function FishAlias n -> Some n | _ -> None) flags
7091         with Not_found -> name in
7092       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7093       let synopsis =
7094         match snd style with
7095         | [] -> name2
7096         | args ->
7097             sprintf "%s %s"
7098               name2 (String.concat " " (List.map name_of_argt args)) in
7099
7100       let warnings =
7101         if List.mem ProtocolLimitWarning flags then
7102           ("\n\n" ^ protocol_limit_warning)
7103         else "" in
7104
7105       (* For DangerWillRobinson commands, we should probably have
7106        * guestfish prompt before allowing you to use them (especially
7107        * in interactive mode). XXX
7108        *)
7109       let warnings =
7110         warnings ^
7111           if List.mem DangerWillRobinson flags then
7112             ("\n\n" ^ danger_will_robinson)
7113           else "" in
7114
7115       let warnings =
7116         warnings ^
7117           match deprecation_notice flags with
7118           | None -> ""
7119           | Some txt -> "\n\n" ^ txt in
7120
7121       let describe_alias =
7122         if name <> alias then
7123           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7124         else "" in
7125
7126       pr "  if (";
7127       pr "STRCASEEQ (cmd, \"%s\")" name;
7128       if name <> name2 then
7129         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7130       if name <> alias then
7131         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7132       pr ")\n";
7133       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7134         name2 shortdesc
7135         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7136          "=head1 DESCRIPTION\n\n" ^
7137          longdesc ^ warnings ^ describe_alias);
7138       pr "  else\n"
7139   ) all_functions;
7140   pr "    display_builtin_command (cmd);\n";
7141   pr "}\n";
7142   pr "\n";
7143
7144   let emit_print_list_function typ =
7145     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7146       typ typ typ;
7147     pr "{\n";
7148     pr "  unsigned int i;\n";
7149     pr "\n";
7150     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7151     pr "    printf (\"[%%d] = {\\n\", i);\n";
7152     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7153     pr "    printf (\"}\\n\");\n";
7154     pr "  }\n";
7155     pr "}\n";
7156     pr "\n";
7157   in
7158
7159   (* print_* functions *)
7160   List.iter (
7161     fun (typ, cols) ->
7162       let needs_i =
7163         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7164
7165       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7166       pr "{\n";
7167       if needs_i then (
7168         pr "  unsigned int i;\n";
7169         pr "\n"
7170       );
7171       List.iter (
7172         function
7173         | name, FString ->
7174             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7175         | name, FUUID ->
7176             pr "  printf (\"%%s%s: \", indent);\n" name;
7177             pr "  for (i = 0; i < 32; ++i)\n";
7178             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7179             pr "  printf (\"\\n\");\n"
7180         | name, FBuffer ->
7181             pr "  printf (\"%%s%s: \", indent);\n" name;
7182             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7183             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7184             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7185             pr "    else\n";
7186             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7187             pr "  printf (\"\\n\");\n"
7188         | name, (FUInt64|FBytes) ->
7189             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7190               name typ name
7191         | name, FInt64 ->
7192             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7193               name typ name
7194         | name, FUInt32 ->
7195             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7196               name typ name
7197         | name, FInt32 ->
7198             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7199               name typ name
7200         | name, FChar ->
7201             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7202               name typ name
7203         | name, FOptPercent ->
7204             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7205               typ name name typ name;
7206             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7207       ) cols;
7208       pr "}\n";
7209       pr "\n";
7210   ) structs;
7211
7212   (* Emit a print_TYPE_list function definition only if that function is used. *)
7213   List.iter (
7214     function
7215     | typ, (RStructListOnly | RStructAndList) ->
7216         (* generate the function for typ *)
7217         emit_print_list_function typ
7218     | typ, _ -> () (* empty *)
7219   ) (rstructs_used_by all_functions);
7220
7221   (* Emit a print_TYPE function definition only if that function is used. *)
7222   List.iter (
7223     function
7224     | typ, (RStructOnly | RStructAndList) ->
7225         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7226         pr "{\n";
7227         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7228         pr "}\n";
7229         pr "\n";
7230     | typ, _ -> () (* empty *)
7231   ) (rstructs_used_by all_functions);
7232
7233   (* run_<action> actions *)
7234   List.iter (
7235     fun (name, style, _, flags, _, _, _) ->
7236       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7237       pr "{\n";
7238       (match fst style with
7239        | RErr
7240        | RInt _
7241        | RBool _ -> pr "  int r;\n"
7242        | RInt64 _ -> pr "  int64_t r;\n"
7243        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7244        | RString _ -> pr "  char *r;\n"
7245        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7246        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7247        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7248        | RBufferOut _ ->
7249            pr "  char *r;\n";
7250            pr "  size_t size;\n";
7251       );
7252       List.iter (
7253         function
7254         | Device n
7255         | String n
7256         | OptString n
7257         | FileIn n
7258         | FileOut n -> pr "  const char *%s;\n" n
7259         | Pathname n
7260         | Dev_or_Path n -> pr "  char *%s;\n" n
7261         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7262         | Bool n -> pr "  int %s;\n" n
7263         | Int n -> pr "  int %s;\n" n
7264         | Int64 n -> pr "  int64_t %s;\n" n
7265       ) (snd style);
7266
7267       (* Check and convert parameters. *)
7268       let argc_expected = List.length (snd style) in
7269       pr "  if (argc != %d) {\n" argc_expected;
7270       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7271         argc_expected;
7272       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7273       pr "    return -1;\n";
7274       pr "  }\n";
7275
7276       let parse_integer fn fntyp rtyp range name i =
7277         pr "  {\n";
7278         pr "    strtol_error xerr;\n";
7279         pr "    %s r;\n" fntyp;
7280         pr "\n";
7281         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7282         pr "    if (xerr != LONGINT_OK) {\n";
7283         pr "      fprintf (stderr,\n";
7284         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7285         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7286         pr "      return -1;\n";
7287         pr "    }\n";
7288         (match range with
7289          | None -> ()
7290          | Some (min, max, comment) ->
7291              pr "    /* %s */\n" comment;
7292              pr "    if (r < %s || r > %s) {\n" min max;
7293              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7294                name;
7295              pr "      return -1;\n";
7296              pr "    }\n";
7297              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7298         );
7299         pr "    %s = r;\n" name;
7300         pr "  }\n";
7301       in
7302
7303       iteri (
7304         fun i ->
7305           function
7306           | Device name
7307           | String name ->
7308               pr "  %s = argv[%d];\n" name i
7309           | Pathname name
7310           | Dev_or_Path name ->
7311               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7312               pr "  if (%s == NULL) return -1;\n" name
7313           | OptString name ->
7314               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7315                 name i i
7316           | FileIn name ->
7317               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7318                 name i i
7319           | FileOut name ->
7320               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7321                 name i i
7322           | StringList name | DeviceList name ->
7323               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7324               pr "  if (%s == NULL) return -1;\n" name;
7325           | Bool name ->
7326               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7327           | Int name ->
7328               let range =
7329                 let min = "(-(2LL<<30))"
7330                 and max = "((2LL<<30)-1)"
7331                 and comment =
7332                   "The Int type in the generator is a signed 31 bit int." in
7333                 Some (min, max, comment) in
7334               parse_integer "xstrtoll" "long long" "int" range name i
7335           | Int64 name ->
7336               parse_integer "xstrtoll" "long long" "int64_t" None name i
7337       ) (snd style);
7338
7339       (* Call C API function. *)
7340       let fn =
7341         try find_map (function FishAction n -> Some n | _ -> None) flags
7342         with Not_found -> sprintf "guestfs_%s" name in
7343       pr "  r = %s " fn;
7344       generate_c_call_args ~handle:"g" style;
7345       pr ";\n";
7346
7347       List.iter (
7348         function
7349         | Device name | String name
7350         | OptString name | FileIn name | FileOut name | Bool name
7351         | Int name | Int64 name -> ()
7352         | Pathname name | Dev_or_Path name ->
7353             pr "  free (%s);\n" name
7354         | StringList name | DeviceList name ->
7355             pr "  free_strings (%s);\n" name
7356       ) (snd style);
7357
7358       (* Check return value for errors and display command results. *)
7359       (match fst style with
7360        | RErr -> pr "  return r;\n"
7361        | RInt _ ->
7362            pr "  if (r == -1) return -1;\n";
7363            pr "  printf (\"%%d\\n\", r);\n";
7364            pr "  return 0;\n"
7365        | RInt64 _ ->
7366            pr "  if (r == -1) return -1;\n";
7367            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7368            pr "  return 0;\n"
7369        | RBool _ ->
7370            pr "  if (r == -1) return -1;\n";
7371            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7372            pr "  return 0;\n"
7373        | RConstString _ ->
7374            pr "  if (r == NULL) return -1;\n";
7375            pr "  printf (\"%%s\\n\", r);\n";
7376            pr "  return 0;\n"
7377        | RConstOptString _ ->
7378            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7379            pr "  return 0;\n"
7380        | RString _ ->
7381            pr "  if (r == NULL) return -1;\n";
7382            pr "  printf (\"%%s\\n\", r);\n";
7383            pr "  free (r);\n";
7384            pr "  return 0;\n"
7385        | RStringList _ ->
7386            pr "  if (r == NULL) return -1;\n";
7387            pr "  print_strings (r);\n";
7388            pr "  free_strings (r);\n";
7389            pr "  return 0;\n"
7390        | RStruct (_, typ) ->
7391            pr "  if (r == NULL) return -1;\n";
7392            pr "  print_%s (r);\n" typ;
7393            pr "  guestfs_free_%s (r);\n" typ;
7394            pr "  return 0;\n"
7395        | RStructList (_, typ) ->
7396            pr "  if (r == NULL) return -1;\n";
7397            pr "  print_%s_list (r);\n" typ;
7398            pr "  guestfs_free_%s_list (r);\n" typ;
7399            pr "  return 0;\n"
7400        | RHashtable _ ->
7401            pr "  if (r == NULL) return -1;\n";
7402            pr "  print_table (r);\n";
7403            pr "  free_strings (r);\n";
7404            pr "  return 0;\n"
7405        | RBufferOut _ ->
7406            pr "  if (r == NULL) return -1;\n";
7407            pr "  if (full_write (1, r, size) != size) {\n";
7408            pr "    perror (\"write\");\n";
7409            pr "    free (r);\n";
7410            pr "    return -1;\n";
7411            pr "  }\n";
7412            pr "  free (r);\n";
7413            pr "  return 0;\n"
7414       );
7415       pr "}\n";
7416       pr "\n"
7417   ) all_functions;
7418
7419   (* run_action function *)
7420   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7421   pr "{\n";
7422   List.iter (
7423     fun (name, _, _, flags, _, _, _) ->
7424       let name2 = replace_char name '_' '-' in
7425       let alias =
7426         try find_map (function FishAlias n -> Some n | _ -> None) flags
7427         with Not_found -> name in
7428       pr "  if (";
7429       pr "STRCASEEQ (cmd, \"%s\")" name;
7430       if name <> name2 then
7431         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7432       if name <> alias then
7433         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7434       pr ")\n";
7435       pr "    return run_%s (cmd, argc, argv);\n" name;
7436       pr "  else\n";
7437   ) all_functions;
7438   pr "    {\n";
7439   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7440   pr "      if (command_num == 1)\n";
7441   pr "        extended_help_message ();\n";
7442   pr "      return -1;\n";
7443   pr "    }\n";
7444   pr "  return 0;\n";
7445   pr "}\n";
7446   pr "\n"
7447
7448 (* Readline completion for guestfish. *)
7449 and generate_fish_completion () =
7450   generate_header CStyle GPLv2plus;
7451
7452   let all_functions =
7453     List.filter (
7454       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7455     ) all_functions in
7456
7457   pr "\
7458 #include <config.h>
7459
7460 #include <stdio.h>
7461 #include <stdlib.h>
7462 #include <string.h>
7463
7464 #ifdef HAVE_LIBREADLINE
7465 #include <readline/readline.h>
7466 #endif
7467
7468 #include \"fish.h\"
7469
7470 #ifdef HAVE_LIBREADLINE
7471
7472 static const char *const commands[] = {
7473   BUILTIN_COMMANDS_FOR_COMPLETION,
7474 ";
7475
7476   (* Get the commands, including the aliases.  They don't need to be
7477    * sorted - the generator() function just does a dumb linear search.
7478    *)
7479   let commands =
7480     List.map (
7481       fun (name, _, _, flags, _, _, _) ->
7482         let name2 = replace_char name '_' '-' in
7483         let alias =
7484           try find_map (function FishAlias n -> Some n | _ -> None) flags
7485           with Not_found -> name in
7486
7487         if name <> alias then [name2; alias] else [name2]
7488     ) all_functions in
7489   let commands = List.flatten commands in
7490
7491   List.iter (pr "  \"%s\",\n") commands;
7492
7493   pr "  NULL
7494 };
7495
7496 static char *
7497 generator (const char *text, int state)
7498 {
7499   static int index, len;
7500   const char *name;
7501
7502   if (!state) {
7503     index = 0;
7504     len = strlen (text);
7505   }
7506
7507   rl_attempted_completion_over = 1;
7508
7509   while ((name = commands[index]) != NULL) {
7510     index++;
7511     if (STRCASEEQLEN (name, text, len))
7512       return strdup (name);
7513   }
7514
7515   return NULL;
7516 }
7517
7518 #endif /* HAVE_LIBREADLINE */
7519
7520 #ifdef HAVE_RL_COMPLETION_MATCHES
7521 #define RL_COMPLETION_MATCHES rl_completion_matches
7522 #else
7523 #ifdef HAVE_COMPLETION_MATCHES
7524 #define RL_COMPLETION_MATCHES completion_matches
7525 #endif
7526 #endif /* else just fail if we don't have either symbol */
7527
7528 char **
7529 do_completion (const char *text, int start, int end)
7530 {
7531   char **matches = NULL;
7532
7533 #ifdef HAVE_LIBREADLINE
7534   rl_completion_append_character = ' ';
7535
7536   if (start == 0)
7537     matches = RL_COMPLETION_MATCHES (text, generator);
7538   else if (complete_dest_paths)
7539     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7540 #endif
7541
7542   return matches;
7543 }
7544 ";
7545
7546 (* Generate the POD documentation for guestfish. *)
7547 and generate_fish_actions_pod () =
7548   let all_functions_sorted =
7549     List.filter (
7550       fun (_, _, _, flags, _, _, _) ->
7551         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7552     ) all_functions_sorted in
7553
7554   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7555
7556   List.iter (
7557     fun (name, style, _, flags, _, _, longdesc) ->
7558       let longdesc =
7559         Str.global_substitute rex (
7560           fun s ->
7561             let sub =
7562               try Str.matched_group 1 s
7563               with Not_found ->
7564                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7565             "C<" ^ replace_char sub '_' '-' ^ ">"
7566         ) longdesc in
7567       let name = replace_char name '_' '-' in
7568       let alias =
7569         try find_map (function FishAlias n -> Some n | _ -> None) flags
7570         with Not_found -> name in
7571
7572       pr "=head2 %s" name;
7573       if name <> alias then
7574         pr " | %s" alias;
7575       pr "\n";
7576       pr "\n";
7577       pr " %s" name;
7578       List.iter (
7579         function
7580         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7581         | OptString n -> pr " %s" n
7582         | StringList n | DeviceList n -> pr " '%s ...'" n
7583         | Bool _ -> pr " true|false"
7584         | Int n -> pr " %s" n
7585         | Int64 n -> pr " %s" n
7586         | FileIn n | FileOut n -> pr " (%s|-)" n
7587       ) (snd style);
7588       pr "\n";
7589       pr "\n";
7590       pr "%s\n\n" longdesc;
7591
7592       if List.exists (function FileIn _ | FileOut _ -> true
7593                       | _ -> false) (snd style) then
7594         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7595
7596       if List.mem ProtocolLimitWarning flags then
7597         pr "%s\n\n" protocol_limit_warning;
7598
7599       if List.mem DangerWillRobinson flags then
7600         pr "%s\n\n" danger_will_robinson;
7601
7602       match deprecation_notice flags with
7603       | None -> ()
7604       | Some txt -> pr "%s\n\n" txt
7605   ) all_functions_sorted
7606
7607 (* Generate a C function prototype. *)
7608 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7609     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7610     ?(prefix = "")
7611     ?handle name style =
7612   if extern then pr "extern ";
7613   if static then pr "static ";
7614   (match fst style with
7615    | RErr -> pr "int "
7616    | RInt _ -> pr "int "
7617    | RInt64 _ -> pr "int64_t "
7618    | RBool _ -> pr "int "
7619    | RConstString _ | RConstOptString _ -> pr "const char *"
7620    | RString _ | RBufferOut _ -> pr "char *"
7621    | RStringList _ | RHashtable _ -> pr "char **"
7622    | RStruct (_, typ) ->
7623        if not in_daemon then pr "struct guestfs_%s *" typ
7624        else pr "guestfs_int_%s *" typ
7625    | RStructList (_, typ) ->
7626        if not in_daemon then pr "struct guestfs_%s_list *" typ
7627        else pr "guestfs_int_%s_list *" typ
7628   );
7629   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7630   pr "%s%s (" prefix name;
7631   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7632     pr "void"
7633   else (
7634     let comma = ref false in
7635     (match handle with
7636      | None -> ()
7637      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7638     );
7639     let next () =
7640       if !comma then (
7641         if single_line then pr ", " else pr ",\n\t\t"
7642       );
7643       comma := true
7644     in
7645     List.iter (
7646       function
7647       | Pathname n
7648       | Device n | Dev_or_Path n
7649       | String n
7650       | OptString n ->
7651           next ();
7652           pr "const char *%s" n
7653       | StringList n | DeviceList n ->
7654           next ();
7655           pr "char *const *%s" n
7656       | Bool n -> next (); pr "int %s" n
7657       | Int n -> next (); pr "int %s" n
7658       | Int64 n -> next (); pr "int64_t %s" n
7659       | FileIn n
7660       | FileOut n ->
7661           if not in_daemon then (next (); pr "const char *%s" n)
7662     ) (snd style);
7663     if is_RBufferOut then (next (); pr "size_t *size_r");
7664   );
7665   pr ")";
7666   if semicolon then pr ";";
7667   if newline then pr "\n"
7668
7669 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7670 and generate_c_call_args ?handle ?(decl = false) style =
7671   pr "(";
7672   let comma = ref false in
7673   let next () =
7674     if !comma then pr ", ";
7675     comma := true
7676   in
7677   (match handle with
7678    | None -> ()
7679    | Some handle -> pr "%s" handle; comma := true
7680   );
7681   List.iter (
7682     fun arg ->
7683       next ();
7684       pr "%s" (name_of_argt arg)
7685   ) (snd style);
7686   (* For RBufferOut calls, add implicit &size parameter. *)
7687   if not decl then (
7688     match fst style with
7689     | RBufferOut _ ->
7690         next ();
7691         pr "&size"
7692     | _ -> ()
7693   );
7694   pr ")"
7695
7696 (* Generate the OCaml bindings interface. *)
7697 and generate_ocaml_mli () =
7698   generate_header OCamlStyle LGPLv2plus;
7699
7700   pr "\
7701 (** For API documentation you should refer to the C API
7702     in the guestfs(3) manual page.  The OCaml API uses almost
7703     exactly the same calls. *)
7704
7705 type t
7706 (** A [guestfs_h] handle. *)
7707
7708 exception Error of string
7709 (** This exception is raised when there is an error. *)
7710
7711 exception Handle_closed of string
7712 (** This exception is raised if you use a {!Guestfs.t} handle
7713     after calling {!close} on it.  The string is the name of
7714     the function. *)
7715
7716 val create : unit -> t
7717 (** Create a {!Guestfs.t} handle. *)
7718
7719 val close : t -> unit
7720 (** Close the {!Guestfs.t} handle and free up all resources used
7721     by it immediately.
7722
7723     Handles are closed by the garbage collector when they become
7724     unreferenced, but callers can call this in order to provide
7725     predictable cleanup. *)
7726
7727 ";
7728   generate_ocaml_structure_decls ();
7729
7730   (* The actions. *)
7731   List.iter (
7732     fun (name, style, _, _, _, shortdesc, _) ->
7733       generate_ocaml_prototype name style;
7734       pr "(** %s *)\n" shortdesc;
7735       pr "\n"
7736   ) all_functions_sorted
7737
7738 (* Generate the OCaml bindings implementation. *)
7739 and generate_ocaml_ml () =
7740   generate_header OCamlStyle LGPLv2plus;
7741
7742   pr "\
7743 type t
7744
7745 exception Error of string
7746 exception Handle_closed of string
7747
7748 external create : unit -> t = \"ocaml_guestfs_create\"
7749 external close : t -> unit = \"ocaml_guestfs_close\"
7750
7751 (* Give the exceptions names, so they can be raised from the C code. *)
7752 let () =
7753   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7754   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7755
7756 ";
7757
7758   generate_ocaml_structure_decls ();
7759
7760   (* The actions. *)
7761   List.iter (
7762     fun (name, style, _, _, _, shortdesc, _) ->
7763       generate_ocaml_prototype ~is_external:true name style;
7764   ) all_functions_sorted
7765
7766 (* Generate the OCaml bindings C implementation. *)
7767 and generate_ocaml_c () =
7768   generate_header CStyle LGPLv2plus;
7769
7770   pr "\
7771 #include <stdio.h>
7772 #include <stdlib.h>
7773 #include <string.h>
7774
7775 #include <caml/config.h>
7776 #include <caml/alloc.h>
7777 #include <caml/callback.h>
7778 #include <caml/fail.h>
7779 #include <caml/memory.h>
7780 #include <caml/mlvalues.h>
7781 #include <caml/signals.h>
7782
7783 #include <guestfs.h>
7784
7785 #include \"guestfs_c.h\"
7786
7787 /* Copy a hashtable of string pairs into an assoc-list.  We return
7788  * the list in reverse order, but hashtables aren't supposed to be
7789  * ordered anyway.
7790  */
7791 static CAMLprim value
7792 copy_table (char * const * argv)
7793 {
7794   CAMLparam0 ();
7795   CAMLlocal5 (rv, pairv, kv, vv, cons);
7796   int i;
7797
7798   rv = Val_int (0);
7799   for (i = 0; argv[i] != NULL; i += 2) {
7800     kv = caml_copy_string (argv[i]);
7801     vv = caml_copy_string (argv[i+1]);
7802     pairv = caml_alloc (2, 0);
7803     Store_field (pairv, 0, kv);
7804     Store_field (pairv, 1, vv);
7805     cons = caml_alloc (2, 0);
7806     Store_field (cons, 1, rv);
7807     rv = cons;
7808     Store_field (cons, 0, pairv);
7809   }
7810
7811   CAMLreturn (rv);
7812 }
7813
7814 ";
7815
7816   (* Struct copy functions. *)
7817
7818   let emit_ocaml_copy_list_function typ =
7819     pr "static CAMLprim value\n";
7820     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7821     pr "{\n";
7822     pr "  CAMLparam0 ();\n";
7823     pr "  CAMLlocal2 (rv, v);\n";
7824     pr "  unsigned int i;\n";
7825     pr "\n";
7826     pr "  if (%ss->len == 0)\n" typ;
7827     pr "    CAMLreturn (Atom (0));\n";
7828     pr "  else {\n";
7829     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7830     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7831     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7832     pr "      caml_modify (&Field (rv, i), v);\n";
7833     pr "    }\n";
7834     pr "    CAMLreturn (rv);\n";
7835     pr "  }\n";
7836     pr "}\n";
7837     pr "\n";
7838   in
7839
7840   List.iter (
7841     fun (typ, cols) ->
7842       let has_optpercent_col =
7843         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7844
7845       pr "static CAMLprim value\n";
7846       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7847       pr "{\n";
7848       pr "  CAMLparam0 ();\n";
7849       if has_optpercent_col then
7850         pr "  CAMLlocal3 (rv, v, v2);\n"
7851       else
7852         pr "  CAMLlocal2 (rv, v);\n";
7853       pr "\n";
7854       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7855       iteri (
7856         fun i col ->
7857           (match col with
7858            | name, FString ->
7859                pr "  v = caml_copy_string (%s->%s);\n" typ name
7860            | name, FBuffer ->
7861                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7862                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7863                  typ name typ name
7864            | name, FUUID ->
7865                pr "  v = caml_alloc_string (32);\n";
7866                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7867            | name, (FBytes|FInt64|FUInt64) ->
7868                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7869            | name, (FInt32|FUInt32) ->
7870                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7871            | name, FOptPercent ->
7872                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7873                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7874                pr "    v = caml_alloc (1, 0);\n";
7875                pr "    Store_field (v, 0, v2);\n";
7876                pr "  } else /* None */\n";
7877                pr "    v = Val_int (0);\n";
7878            | name, FChar ->
7879                pr "  v = Val_int (%s->%s);\n" typ name
7880           );
7881           pr "  Store_field (rv, %d, v);\n" i
7882       ) cols;
7883       pr "  CAMLreturn (rv);\n";
7884       pr "}\n";
7885       pr "\n";
7886   ) structs;
7887
7888   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7889   List.iter (
7890     function
7891     | typ, (RStructListOnly | RStructAndList) ->
7892         (* generate the function for typ *)
7893         emit_ocaml_copy_list_function typ
7894     | typ, _ -> () (* empty *)
7895   ) (rstructs_used_by all_functions);
7896
7897   (* The wrappers. *)
7898   List.iter (
7899     fun (name, style, _, _, _, _, _) ->
7900       pr "/* Automatically generated wrapper for function\n";
7901       pr " * ";
7902       generate_ocaml_prototype name style;
7903       pr " */\n";
7904       pr "\n";
7905
7906       let params =
7907         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7908
7909       let needs_extra_vs =
7910         match fst style with RConstOptString _ -> true | _ -> false in
7911
7912       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7913       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7914       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7915       pr "\n";
7916
7917       pr "CAMLprim value\n";
7918       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7919       List.iter (pr ", value %s") (List.tl params);
7920       pr ")\n";
7921       pr "{\n";
7922
7923       (match params with
7924        | [p1; p2; p3; p4; p5] ->
7925            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7926        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7927            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7928            pr "  CAMLxparam%d (%s);\n"
7929              (List.length rest) (String.concat ", " rest)
7930        | ps ->
7931            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7932       );
7933       if not needs_extra_vs then
7934         pr "  CAMLlocal1 (rv);\n"
7935       else
7936         pr "  CAMLlocal3 (rv, v, v2);\n";
7937       pr "\n";
7938
7939       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7940       pr "  if (g == NULL)\n";
7941       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7942       pr "\n";
7943
7944       List.iter (
7945         function
7946         | Pathname n
7947         | Device n | Dev_or_Path n
7948         | String n
7949         | FileIn n
7950         | FileOut n ->
7951             pr "  const char *%s = String_val (%sv);\n" n n
7952         | OptString n ->
7953             pr "  const char *%s =\n" n;
7954             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7955               n n
7956         | StringList n | DeviceList n ->
7957             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7958         | Bool n ->
7959             pr "  int %s = Bool_val (%sv);\n" n n
7960         | Int n ->
7961             pr "  int %s = Int_val (%sv);\n" n n
7962         | Int64 n ->
7963             pr "  int64_t %s = Int64_val (%sv);\n" n n
7964       ) (snd style);
7965       let error_code =
7966         match fst style with
7967         | RErr -> pr "  int r;\n"; "-1"
7968         | RInt _ -> pr "  int r;\n"; "-1"
7969         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7970         | RBool _ -> pr "  int r;\n"; "-1"
7971         | RConstString _ | RConstOptString _ ->
7972             pr "  const char *r;\n"; "NULL"
7973         | RString _ -> pr "  char *r;\n"; "NULL"
7974         | RStringList _ ->
7975             pr "  int i;\n";
7976             pr "  char **r;\n";
7977             "NULL"
7978         | RStruct (_, typ) ->
7979             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7980         | RStructList (_, typ) ->
7981             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7982         | RHashtable _ ->
7983             pr "  int i;\n";
7984             pr "  char **r;\n";
7985             "NULL"
7986         | RBufferOut _ ->
7987             pr "  char *r;\n";
7988             pr "  size_t size;\n";
7989             "NULL" in
7990       pr "\n";
7991
7992       pr "  caml_enter_blocking_section ();\n";
7993       pr "  r = guestfs_%s " name;
7994       generate_c_call_args ~handle:"g" style;
7995       pr ";\n";
7996       pr "  caml_leave_blocking_section ();\n";
7997
7998       List.iter (
7999         function
8000         | StringList n | DeviceList n ->
8001             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8002         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8003         | Bool _ | Int _ | Int64 _
8004         | FileIn _ | FileOut _ -> ()
8005       ) (snd style);
8006
8007       pr "  if (r == %s)\n" error_code;
8008       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8009       pr "\n";
8010
8011       (match fst style with
8012        | RErr -> pr "  rv = Val_unit;\n"
8013        | RInt _ -> pr "  rv = Val_int (r);\n"
8014        | RInt64 _ ->
8015            pr "  rv = caml_copy_int64 (r);\n"
8016        | RBool _ -> pr "  rv = Val_bool (r);\n"
8017        | RConstString _ ->
8018            pr "  rv = caml_copy_string (r);\n"
8019        | RConstOptString _ ->
8020            pr "  if (r) { /* Some string */\n";
8021            pr "    v = caml_alloc (1, 0);\n";
8022            pr "    v2 = caml_copy_string (r);\n";
8023            pr "    Store_field (v, 0, v2);\n";
8024            pr "  } else /* None */\n";
8025            pr "    v = Val_int (0);\n";
8026        | RString _ ->
8027            pr "  rv = caml_copy_string (r);\n";
8028            pr "  free (r);\n"
8029        | RStringList _ ->
8030            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8031            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8032            pr "  free (r);\n"
8033        | RStruct (_, typ) ->
8034            pr "  rv = copy_%s (r);\n" typ;
8035            pr "  guestfs_free_%s (r);\n" typ;
8036        | RStructList (_, typ) ->
8037            pr "  rv = copy_%s_list (r);\n" typ;
8038            pr "  guestfs_free_%s_list (r);\n" typ;
8039        | RHashtable _ ->
8040            pr "  rv = copy_table (r);\n";
8041            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8042            pr "  free (r);\n";
8043        | RBufferOut _ ->
8044            pr "  rv = caml_alloc_string (size);\n";
8045            pr "  memcpy (String_val (rv), r, size);\n";
8046       );
8047
8048       pr "  CAMLreturn (rv);\n";
8049       pr "}\n";
8050       pr "\n";
8051
8052       if List.length params > 5 then (
8053         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8054         pr "CAMLprim value ";
8055         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8056         pr "CAMLprim value\n";
8057         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8058         pr "{\n";
8059         pr "  return ocaml_guestfs_%s (argv[0]" name;
8060         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8061         pr ");\n";
8062         pr "}\n";
8063         pr "\n"
8064       )
8065   ) all_functions_sorted
8066
8067 and generate_ocaml_structure_decls () =
8068   List.iter (
8069     fun (typ, cols) ->
8070       pr "type %s = {\n" typ;
8071       List.iter (
8072         function
8073         | name, FString -> pr "  %s : string;\n" name
8074         | name, FBuffer -> pr "  %s : string;\n" name
8075         | name, FUUID -> pr "  %s : string;\n" name
8076         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8077         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8078         | name, FChar -> pr "  %s : char;\n" name
8079         | name, FOptPercent -> pr "  %s : float option;\n" name
8080       ) cols;
8081       pr "}\n";
8082       pr "\n"
8083   ) structs
8084
8085 and generate_ocaml_prototype ?(is_external = false) name style =
8086   if is_external then pr "external " else pr "val ";
8087   pr "%s : t -> " name;
8088   List.iter (
8089     function
8090     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8091     | OptString _ -> pr "string option -> "
8092     | StringList _ | DeviceList _ -> pr "string array -> "
8093     | Bool _ -> pr "bool -> "
8094     | Int _ -> pr "int -> "
8095     | Int64 _ -> pr "int64 -> "
8096   ) (snd style);
8097   (match fst style with
8098    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8099    | RInt _ -> pr "int"
8100    | RInt64 _ -> pr "int64"
8101    | RBool _ -> pr "bool"
8102    | RConstString _ -> pr "string"
8103    | RConstOptString _ -> pr "string option"
8104    | RString _ | RBufferOut _ -> pr "string"
8105    | RStringList _ -> pr "string array"
8106    | RStruct (_, typ) -> pr "%s" typ
8107    | RStructList (_, typ) -> pr "%s array" typ
8108    | RHashtable _ -> pr "(string * string) list"
8109   );
8110   if is_external then (
8111     pr " = ";
8112     if List.length (snd style) + 1 > 5 then
8113       pr "\"ocaml_guestfs_%s_byte\" " name;
8114     pr "\"ocaml_guestfs_%s\"" name
8115   );
8116   pr "\n"
8117
8118 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8119 and generate_perl_xs () =
8120   generate_header CStyle LGPLv2plus;
8121
8122   pr "\
8123 #include \"EXTERN.h\"
8124 #include \"perl.h\"
8125 #include \"XSUB.h\"
8126
8127 #include <guestfs.h>
8128
8129 #ifndef PRId64
8130 #define PRId64 \"lld\"
8131 #endif
8132
8133 static SV *
8134 my_newSVll(long long val) {
8135 #ifdef USE_64_BIT_ALL
8136   return newSViv(val);
8137 #else
8138   char buf[100];
8139   int len;
8140   len = snprintf(buf, 100, \"%%\" PRId64, val);
8141   return newSVpv(buf, len);
8142 #endif
8143 }
8144
8145 #ifndef PRIu64
8146 #define PRIu64 \"llu\"
8147 #endif
8148
8149 static SV *
8150 my_newSVull(unsigned long long val) {
8151 #ifdef USE_64_BIT_ALL
8152   return newSVuv(val);
8153 #else
8154   char buf[100];
8155   int len;
8156   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8157   return newSVpv(buf, len);
8158 #endif
8159 }
8160
8161 /* http://www.perlmonks.org/?node_id=680842 */
8162 static char **
8163 XS_unpack_charPtrPtr (SV *arg) {
8164   char **ret;
8165   AV *av;
8166   I32 i;
8167
8168   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8169     croak (\"array reference expected\");
8170
8171   av = (AV *)SvRV (arg);
8172   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8173   if (!ret)
8174     croak (\"malloc failed\");
8175
8176   for (i = 0; i <= av_len (av); i++) {
8177     SV **elem = av_fetch (av, i, 0);
8178
8179     if (!elem || !*elem)
8180       croak (\"missing element in list\");
8181
8182     ret[i] = SvPV_nolen (*elem);
8183   }
8184
8185   ret[i] = NULL;
8186
8187   return ret;
8188 }
8189
8190 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8191
8192 PROTOTYPES: ENABLE
8193
8194 guestfs_h *
8195 _create ()
8196    CODE:
8197       RETVAL = guestfs_create ();
8198       if (!RETVAL)
8199         croak (\"could not create guestfs handle\");
8200       guestfs_set_error_handler (RETVAL, NULL, NULL);
8201  OUTPUT:
8202       RETVAL
8203
8204 void
8205 DESTROY (g)
8206       guestfs_h *g;
8207  PPCODE:
8208       guestfs_close (g);
8209
8210 ";
8211
8212   List.iter (
8213     fun (name, style, _, _, _, _, _) ->
8214       (match fst style with
8215        | RErr -> pr "void\n"
8216        | RInt _ -> pr "SV *\n"
8217        | RInt64 _ -> pr "SV *\n"
8218        | RBool _ -> pr "SV *\n"
8219        | RConstString _ -> pr "SV *\n"
8220        | RConstOptString _ -> pr "SV *\n"
8221        | RString _ -> pr "SV *\n"
8222        | RBufferOut _ -> pr "SV *\n"
8223        | RStringList _
8224        | RStruct _ | RStructList _
8225        | RHashtable _ ->
8226            pr "void\n" (* all lists returned implictly on the stack *)
8227       );
8228       (* Call and arguments. *)
8229       pr "%s " name;
8230       generate_c_call_args ~handle:"g" ~decl:true style;
8231       pr "\n";
8232       pr "      guestfs_h *g;\n";
8233       iteri (
8234         fun i ->
8235           function
8236           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8237               pr "      char *%s;\n" n
8238           | OptString n ->
8239               (* http://www.perlmonks.org/?node_id=554277
8240                * Note that the implicit handle argument means we have
8241                * to add 1 to the ST(x) operator.
8242                *)
8243               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8244           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8245           | Bool n -> pr "      int %s;\n" n
8246           | Int n -> pr "      int %s;\n" n
8247           | Int64 n -> pr "      int64_t %s;\n" n
8248       ) (snd style);
8249
8250       let do_cleanups () =
8251         List.iter (
8252           function
8253           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8254           | Bool _ | Int _ | Int64 _
8255           | FileIn _ | FileOut _ -> ()
8256           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8257         ) (snd style)
8258       in
8259
8260       (* Code. *)
8261       (match fst style with
8262        | RErr ->
8263            pr "PREINIT:\n";
8264            pr "      int r;\n";
8265            pr " PPCODE:\n";
8266            pr "      r = guestfs_%s " name;
8267            generate_c_call_args ~handle:"g" style;
8268            pr ";\n";
8269            do_cleanups ();
8270            pr "      if (r == -1)\n";
8271            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8272        | RInt n
8273        | RBool n ->
8274            pr "PREINIT:\n";
8275            pr "      int %s;\n" n;
8276            pr "   CODE:\n";
8277            pr "      %s = guestfs_%s " n name;
8278            generate_c_call_args ~handle:"g" style;
8279            pr ";\n";
8280            do_cleanups ();
8281            pr "      if (%s == -1)\n" n;
8282            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8283            pr "      RETVAL = newSViv (%s);\n" n;
8284            pr " OUTPUT:\n";
8285            pr "      RETVAL\n"
8286        | RInt64 n ->
8287            pr "PREINIT:\n";
8288            pr "      int64_t %s;\n" n;
8289            pr "   CODE:\n";
8290            pr "      %s = guestfs_%s " n name;
8291            generate_c_call_args ~handle:"g" style;
8292            pr ";\n";
8293            do_cleanups ();
8294            pr "      if (%s == -1)\n" n;
8295            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8296            pr "      RETVAL = my_newSVll (%s);\n" n;
8297            pr " OUTPUT:\n";
8298            pr "      RETVAL\n"
8299        | RConstString n ->
8300            pr "PREINIT:\n";
8301            pr "      const char *%s;\n" n;
8302            pr "   CODE:\n";
8303            pr "      %s = guestfs_%s " n name;
8304            generate_c_call_args ~handle:"g" style;
8305            pr ";\n";
8306            do_cleanups ();
8307            pr "      if (%s == NULL)\n" n;
8308            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8309            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8310            pr " OUTPUT:\n";
8311            pr "      RETVAL\n"
8312        | RConstOptString n ->
8313            pr "PREINIT:\n";
8314            pr "      const char *%s;\n" n;
8315            pr "   CODE:\n";
8316            pr "      %s = guestfs_%s " n name;
8317            generate_c_call_args ~handle:"g" style;
8318            pr ";\n";
8319            do_cleanups ();
8320            pr "      if (%s == NULL)\n" n;
8321            pr "        RETVAL = &PL_sv_undef;\n";
8322            pr "      else\n";
8323            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8324            pr " OUTPUT:\n";
8325            pr "      RETVAL\n"
8326        | RString n ->
8327            pr "PREINIT:\n";
8328            pr "      char *%s;\n" n;
8329            pr "   CODE:\n";
8330            pr "      %s = guestfs_%s " n name;
8331            generate_c_call_args ~handle:"g" style;
8332            pr ";\n";
8333            do_cleanups ();
8334            pr "      if (%s == NULL)\n" n;
8335            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8336            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8337            pr "      free (%s);\n" n;
8338            pr " OUTPUT:\n";
8339            pr "      RETVAL\n"
8340        | RStringList n | RHashtable n ->
8341            pr "PREINIT:\n";
8342            pr "      char **%s;\n" n;
8343            pr "      int i, n;\n";
8344            pr " PPCODE:\n";
8345            pr "      %s = guestfs_%s " n name;
8346            generate_c_call_args ~handle:"g" style;
8347            pr ";\n";
8348            do_cleanups ();
8349            pr "      if (%s == NULL)\n" n;
8350            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8351            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8352            pr "      EXTEND (SP, n);\n";
8353            pr "      for (i = 0; i < n; ++i) {\n";
8354            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8355            pr "        free (%s[i]);\n" n;
8356            pr "      }\n";
8357            pr "      free (%s);\n" n;
8358        | RStruct (n, typ) ->
8359            let cols = cols_of_struct typ in
8360            generate_perl_struct_code typ cols name style n do_cleanups
8361        | RStructList (n, typ) ->
8362            let cols = cols_of_struct typ in
8363            generate_perl_struct_list_code typ cols name style n do_cleanups
8364        | RBufferOut n ->
8365            pr "PREINIT:\n";
8366            pr "      char *%s;\n" n;
8367            pr "      size_t size;\n";
8368            pr "   CODE:\n";
8369            pr "      %s = guestfs_%s " n name;
8370            generate_c_call_args ~handle:"g" style;
8371            pr ";\n";
8372            do_cleanups ();
8373            pr "      if (%s == NULL)\n" n;
8374            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8375            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8376            pr "      free (%s);\n" n;
8377            pr " OUTPUT:\n";
8378            pr "      RETVAL\n"
8379       );
8380
8381       pr "\n"
8382   ) all_functions
8383
8384 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8385   pr "PREINIT:\n";
8386   pr "      struct guestfs_%s_list *%s;\n" typ n;
8387   pr "      int i;\n";
8388   pr "      HV *hv;\n";
8389   pr " PPCODE:\n";
8390   pr "      %s = guestfs_%s " n name;
8391   generate_c_call_args ~handle:"g" style;
8392   pr ";\n";
8393   do_cleanups ();
8394   pr "      if (%s == NULL)\n" n;
8395   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8396   pr "      EXTEND (SP, %s->len);\n" n;
8397   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8398   pr "        hv = newHV ();\n";
8399   List.iter (
8400     function
8401     | name, FString ->
8402         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8403           name (String.length name) n name
8404     | name, FUUID ->
8405         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8406           name (String.length name) n name
8407     | name, FBuffer ->
8408         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8409           name (String.length name) n name n name
8410     | name, (FBytes|FUInt64) ->
8411         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8412           name (String.length name) n name
8413     | name, FInt64 ->
8414         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8415           name (String.length name) n name
8416     | name, (FInt32|FUInt32) ->
8417         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8418           name (String.length name) n name
8419     | name, FChar ->
8420         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8421           name (String.length name) n name
8422     | name, FOptPercent ->
8423         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8424           name (String.length name) n name
8425   ) cols;
8426   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8427   pr "      }\n";
8428   pr "      guestfs_free_%s_list (%s);\n" typ n
8429
8430 and generate_perl_struct_code typ cols name style n do_cleanups =
8431   pr "PREINIT:\n";
8432   pr "      struct guestfs_%s *%s;\n" typ n;
8433   pr " PPCODE:\n";
8434   pr "      %s = guestfs_%s " n name;
8435   generate_c_call_args ~handle:"g" style;
8436   pr ";\n";
8437   do_cleanups ();
8438   pr "      if (%s == NULL)\n" n;
8439   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8440   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8441   List.iter (
8442     fun ((name, _) as col) ->
8443       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8444
8445       match col with
8446       | name, FString ->
8447           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8448             n name
8449       | name, FBuffer ->
8450           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8451             n name n name
8452       | name, FUUID ->
8453           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8454             n name
8455       | name, (FBytes|FUInt64) ->
8456           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8457             n name
8458       | name, FInt64 ->
8459           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8460             n name
8461       | name, (FInt32|FUInt32) ->
8462           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8463             n name
8464       | name, FChar ->
8465           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8466             n name
8467       | name, FOptPercent ->
8468           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8469             n name
8470   ) cols;
8471   pr "      free (%s);\n" n
8472
8473 (* Generate Sys/Guestfs.pm. *)
8474 and generate_perl_pm () =
8475   generate_header HashStyle LGPLv2plus;
8476
8477   pr "\
8478 =pod
8479
8480 =head1 NAME
8481
8482 Sys::Guestfs - Perl bindings for libguestfs
8483
8484 =head1 SYNOPSIS
8485
8486  use Sys::Guestfs;
8487
8488  my $h = Sys::Guestfs->new ();
8489  $h->add_drive ('guest.img');
8490  $h->launch ();
8491  $h->mount ('/dev/sda1', '/');
8492  $h->touch ('/hello');
8493  $h->sync ();
8494
8495 =head1 DESCRIPTION
8496
8497 The C<Sys::Guestfs> module provides a Perl XS binding to the
8498 libguestfs API for examining and modifying virtual machine
8499 disk images.
8500
8501 Amongst the things this is good for: making batch configuration
8502 changes to guests, getting disk used/free statistics (see also:
8503 virt-df), migrating between virtualization systems (see also:
8504 virt-p2v), performing partial backups, performing partial guest
8505 clones, cloning guests and changing registry/UUID/hostname info, and
8506 much else besides.
8507
8508 Libguestfs uses Linux kernel and qemu code, and can access any type of
8509 guest filesystem that Linux and qemu can, including but not limited
8510 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8511 schemes, qcow, qcow2, vmdk.
8512
8513 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8514 LVs, what filesystem is in each LV, etc.).  It can also run commands
8515 in the context of the guest.  Also you can access filesystems over
8516 FUSE.
8517
8518 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8519 functions for using libguestfs from Perl, including integration
8520 with libvirt.
8521
8522 =head1 ERRORS
8523
8524 All errors turn into calls to C<croak> (see L<Carp(3)>).
8525
8526 =head1 METHODS
8527
8528 =over 4
8529
8530 =cut
8531
8532 package Sys::Guestfs;
8533
8534 use strict;
8535 use warnings;
8536
8537 require XSLoader;
8538 XSLoader::load ('Sys::Guestfs');
8539
8540 =item $h = Sys::Guestfs->new ();
8541
8542 Create a new guestfs handle.
8543
8544 =cut
8545
8546 sub new {
8547   my $proto = shift;
8548   my $class = ref ($proto) || $proto;
8549
8550   my $self = Sys::Guestfs::_create ();
8551   bless $self, $class;
8552   return $self;
8553 }
8554
8555 ";
8556
8557   (* Actions.  We only need to print documentation for these as
8558    * they are pulled in from the XS code automatically.
8559    *)
8560   List.iter (
8561     fun (name, style, _, flags, _, _, longdesc) ->
8562       if not (List.mem NotInDocs flags) then (
8563         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8564         pr "=item ";
8565         generate_perl_prototype name style;
8566         pr "\n\n";
8567         pr "%s\n\n" longdesc;
8568         if List.mem ProtocolLimitWarning flags then
8569           pr "%s\n\n" protocol_limit_warning;
8570         if List.mem DangerWillRobinson flags then
8571           pr "%s\n\n" danger_will_robinson;
8572         match deprecation_notice flags with
8573         | None -> ()
8574         | Some txt -> pr "%s\n\n" txt
8575       )
8576   ) all_functions_sorted;
8577
8578   (* End of file. *)
8579   pr "\
8580 =cut
8581
8582 1;
8583
8584 =back
8585
8586 =head1 COPYRIGHT
8587
8588 Copyright (C) %s Red Hat Inc.
8589
8590 =head1 LICENSE
8591
8592 Please see the file COPYING.LIB for the full license.
8593
8594 =head1 SEE ALSO
8595
8596 L<guestfs(3)>,
8597 L<guestfish(1)>,
8598 L<http://libguestfs.org>,
8599 L<Sys::Guestfs::Lib(3)>.
8600
8601 =cut
8602 " copyright_years
8603
8604 and generate_perl_prototype name style =
8605   (match fst style with
8606    | RErr -> ()
8607    | RBool n
8608    | RInt n
8609    | RInt64 n
8610    | RConstString n
8611    | RConstOptString n
8612    | RString n
8613    | RBufferOut n -> pr "$%s = " n
8614    | RStruct (n,_)
8615    | RHashtable n -> pr "%%%s = " n
8616    | RStringList n
8617    | RStructList (n,_) -> pr "@%s = " n
8618   );
8619   pr "$h->%s (" name;
8620   let comma = ref false in
8621   List.iter (
8622     fun arg ->
8623       if !comma then pr ", ";
8624       comma := true;
8625       match arg with
8626       | Pathname n | Device n | Dev_or_Path n | String n
8627       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8628           pr "$%s" n
8629       | StringList n | DeviceList n ->
8630           pr "\\@%s" n
8631   ) (snd style);
8632   pr ");"
8633
8634 (* Generate Python C module. *)
8635 and generate_python_c () =
8636   generate_header CStyle LGPLv2plus;
8637
8638   pr "\
8639 #include <Python.h>
8640
8641 #include <stdio.h>
8642 #include <stdlib.h>
8643 #include <assert.h>
8644
8645 #include \"guestfs.h\"
8646
8647 typedef struct {
8648   PyObject_HEAD
8649   guestfs_h *g;
8650 } Pyguestfs_Object;
8651
8652 static guestfs_h *
8653 get_handle (PyObject *obj)
8654 {
8655   assert (obj);
8656   assert (obj != Py_None);
8657   return ((Pyguestfs_Object *) obj)->g;
8658 }
8659
8660 static PyObject *
8661 put_handle (guestfs_h *g)
8662 {
8663   assert (g);
8664   return
8665     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8666 }
8667
8668 /* This list should be freed (but not the strings) after use. */
8669 static char **
8670 get_string_list (PyObject *obj)
8671 {
8672   int i, len;
8673   char **r;
8674
8675   assert (obj);
8676
8677   if (!PyList_Check (obj)) {
8678     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8679     return NULL;
8680   }
8681
8682   len = PyList_Size (obj);
8683   r = malloc (sizeof (char *) * (len+1));
8684   if (r == NULL) {
8685     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8686     return NULL;
8687   }
8688
8689   for (i = 0; i < len; ++i)
8690     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8691   r[len] = NULL;
8692
8693   return r;
8694 }
8695
8696 static PyObject *
8697 put_string_list (char * const * const argv)
8698 {
8699   PyObject *list;
8700   int argc, i;
8701
8702   for (argc = 0; argv[argc] != NULL; ++argc)
8703     ;
8704
8705   list = PyList_New (argc);
8706   for (i = 0; i < argc; ++i)
8707     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8708
8709   return list;
8710 }
8711
8712 static PyObject *
8713 put_table (char * const * const argv)
8714 {
8715   PyObject *list, *item;
8716   int argc, i;
8717
8718   for (argc = 0; argv[argc] != NULL; ++argc)
8719     ;
8720
8721   list = PyList_New (argc >> 1);
8722   for (i = 0; i < argc; i += 2) {
8723     item = PyTuple_New (2);
8724     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8725     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8726     PyList_SetItem (list, i >> 1, item);
8727   }
8728
8729   return list;
8730 }
8731
8732 static void
8733 free_strings (char **argv)
8734 {
8735   int argc;
8736
8737   for (argc = 0; argv[argc] != NULL; ++argc)
8738     free (argv[argc]);
8739   free (argv);
8740 }
8741
8742 static PyObject *
8743 py_guestfs_create (PyObject *self, PyObject *args)
8744 {
8745   guestfs_h *g;
8746
8747   g = guestfs_create ();
8748   if (g == NULL) {
8749     PyErr_SetString (PyExc_RuntimeError,
8750                      \"guestfs.create: failed to allocate handle\");
8751     return NULL;
8752   }
8753   guestfs_set_error_handler (g, NULL, NULL);
8754   return put_handle (g);
8755 }
8756
8757 static PyObject *
8758 py_guestfs_close (PyObject *self, PyObject *args)
8759 {
8760   PyObject *py_g;
8761   guestfs_h *g;
8762
8763   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8764     return NULL;
8765   g = get_handle (py_g);
8766
8767   guestfs_close (g);
8768
8769   Py_INCREF (Py_None);
8770   return Py_None;
8771 }
8772
8773 ";
8774
8775   let emit_put_list_function typ =
8776     pr "static PyObject *\n";
8777     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8778     pr "{\n";
8779     pr "  PyObject *list;\n";
8780     pr "  int i;\n";
8781     pr "\n";
8782     pr "  list = PyList_New (%ss->len);\n" typ;
8783     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8784     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8785     pr "  return list;\n";
8786     pr "};\n";
8787     pr "\n"
8788   in
8789
8790   (* Structures, turned into Python dictionaries. *)
8791   List.iter (
8792     fun (typ, cols) ->
8793       pr "static PyObject *\n";
8794       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8795       pr "{\n";
8796       pr "  PyObject *dict;\n";
8797       pr "\n";
8798       pr "  dict = PyDict_New ();\n";
8799       List.iter (
8800         function
8801         | name, FString ->
8802             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8803             pr "                        PyString_FromString (%s->%s));\n"
8804               typ name
8805         | name, FBuffer ->
8806             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8807             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8808               typ name typ name
8809         | name, FUUID ->
8810             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8811             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8812               typ name
8813         | name, (FBytes|FUInt64) ->
8814             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8815             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8816               typ name
8817         | name, FInt64 ->
8818             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8819             pr "                        PyLong_FromLongLong (%s->%s));\n"
8820               typ name
8821         | name, FUInt32 ->
8822             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8823             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8824               typ name
8825         | name, FInt32 ->
8826             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8827             pr "                        PyLong_FromLong (%s->%s));\n"
8828               typ name
8829         | name, FOptPercent ->
8830             pr "  if (%s->%s >= 0)\n" typ name;
8831             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8832             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8833               typ name;
8834             pr "  else {\n";
8835             pr "    Py_INCREF (Py_None);\n";
8836             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8837             pr "  }\n"
8838         | name, FChar ->
8839             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8840             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8841       ) cols;
8842       pr "  return dict;\n";
8843       pr "};\n";
8844       pr "\n";
8845
8846   ) structs;
8847
8848   (* Emit a put_TYPE_list function definition only if that function is used. *)
8849   List.iter (
8850     function
8851     | typ, (RStructListOnly | RStructAndList) ->
8852         (* generate the function for typ *)
8853         emit_put_list_function typ
8854     | typ, _ -> () (* empty *)
8855   ) (rstructs_used_by all_functions);
8856
8857   (* Python wrapper functions. *)
8858   List.iter (
8859     fun (name, style, _, _, _, _, _) ->
8860       pr "static PyObject *\n";
8861       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8862       pr "{\n";
8863
8864       pr "  PyObject *py_g;\n";
8865       pr "  guestfs_h *g;\n";
8866       pr "  PyObject *py_r;\n";
8867
8868       let error_code =
8869         match fst style with
8870         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8871         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8872         | RConstString _ | RConstOptString _ ->
8873             pr "  const char *r;\n"; "NULL"
8874         | RString _ -> pr "  char *r;\n"; "NULL"
8875         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8876         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8877         | RStructList (_, typ) ->
8878             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8879         | RBufferOut _ ->
8880             pr "  char *r;\n";
8881             pr "  size_t size;\n";
8882             "NULL" in
8883
8884       List.iter (
8885         function
8886         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8887             pr "  const char *%s;\n" n
8888         | OptString n -> pr "  const char *%s;\n" n
8889         | StringList n | DeviceList n ->
8890             pr "  PyObject *py_%s;\n" n;
8891             pr "  char **%s;\n" n
8892         | Bool n -> pr "  int %s;\n" n
8893         | Int n -> pr "  int %s;\n" n
8894         | Int64 n -> pr "  long long %s;\n" n
8895       ) (snd style);
8896
8897       pr "\n";
8898
8899       (* Convert the parameters. *)
8900       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8901       List.iter (
8902         function
8903         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8904         | OptString _ -> pr "z"
8905         | StringList _ | DeviceList _ -> pr "O"
8906         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8907         | Int _ -> pr "i"
8908         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8909                              * emulate C's int/long/long long in Python?
8910                              *)
8911       ) (snd style);
8912       pr ":guestfs_%s\",\n" name;
8913       pr "                         &py_g";
8914       List.iter (
8915         function
8916         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8917         | OptString n -> pr ", &%s" n
8918         | StringList n | DeviceList n -> pr ", &py_%s" n
8919         | Bool n -> pr ", &%s" n
8920         | Int n -> pr ", &%s" n
8921         | Int64 n -> pr ", &%s" n
8922       ) (snd style);
8923
8924       pr "))\n";
8925       pr "    return NULL;\n";
8926
8927       pr "  g = get_handle (py_g);\n";
8928       List.iter (
8929         function
8930         | Pathname _ | Device _ | Dev_or_Path _ | String _
8931         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8932         | StringList n | DeviceList n ->
8933             pr "  %s = get_string_list (py_%s);\n" n n;
8934             pr "  if (!%s) return NULL;\n" n
8935       ) (snd style);
8936
8937       pr "\n";
8938
8939       pr "  r = guestfs_%s " name;
8940       generate_c_call_args ~handle:"g" style;
8941       pr ";\n";
8942
8943       List.iter (
8944         function
8945         | Pathname _ | Device _ | Dev_or_Path _ | String _
8946         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8947         | StringList n | DeviceList n ->
8948             pr "  free (%s);\n" n
8949       ) (snd style);
8950
8951       pr "  if (r == %s) {\n" error_code;
8952       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8953       pr "    return NULL;\n";
8954       pr "  }\n";
8955       pr "\n";
8956
8957       (match fst style with
8958        | RErr ->
8959            pr "  Py_INCREF (Py_None);\n";
8960            pr "  py_r = Py_None;\n"
8961        | RInt _
8962        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8963        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8964        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8965        | RConstOptString _ ->
8966            pr "  if (r)\n";
8967            pr "    py_r = PyString_FromString (r);\n";
8968            pr "  else {\n";
8969            pr "    Py_INCREF (Py_None);\n";
8970            pr "    py_r = Py_None;\n";
8971            pr "  }\n"
8972        | RString _ ->
8973            pr "  py_r = PyString_FromString (r);\n";
8974            pr "  free (r);\n"
8975        | RStringList _ ->
8976            pr "  py_r = put_string_list (r);\n";
8977            pr "  free_strings (r);\n"
8978        | RStruct (_, typ) ->
8979            pr "  py_r = put_%s (r);\n" typ;
8980            pr "  guestfs_free_%s (r);\n" typ
8981        | RStructList (_, typ) ->
8982            pr "  py_r = put_%s_list (r);\n" typ;
8983            pr "  guestfs_free_%s_list (r);\n" typ
8984        | RHashtable n ->
8985            pr "  py_r = put_table (r);\n";
8986            pr "  free_strings (r);\n"
8987        | RBufferOut _ ->
8988            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8989            pr "  free (r);\n"
8990       );
8991
8992       pr "  return py_r;\n";
8993       pr "}\n";
8994       pr "\n"
8995   ) all_functions;
8996
8997   (* Table of functions. *)
8998   pr "static PyMethodDef methods[] = {\n";
8999   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9000   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9001   List.iter (
9002     fun (name, _, _, _, _, _, _) ->
9003       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9004         name name
9005   ) all_functions;
9006   pr "  { NULL, NULL, 0, NULL }\n";
9007   pr "};\n";
9008   pr "\n";
9009
9010   (* Init function. *)
9011   pr "\
9012 void
9013 initlibguestfsmod (void)
9014 {
9015   static int initialized = 0;
9016
9017   if (initialized) return;
9018   Py_InitModule ((char *) \"libguestfsmod\", methods);
9019   initialized = 1;
9020 }
9021 "
9022
9023 (* Generate Python module. *)
9024 and generate_python_py () =
9025   generate_header HashStyle LGPLv2plus;
9026
9027   pr "\
9028 u\"\"\"Python bindings for libguestfs
9029
9030 import guestfs
9031 g = guestfs.GuestFS ()
9032 g.add_drive (\"guest.img\")
9033 g.launch ()
9034 parts = g.list_partitions ()
9035
9036 The guestfs module provides a Python binding to the libguestfs API
9037 for examining and modifying virtual machine disk images.
9038
9039 Amongst the things this is good for: making batch configuration
9040 changes to guests, getting disk used/free statistics (see also:
9041 virt-df), migrating between virtualization systems (see also:
9042 virt-p2v), performing partial backups, performing partial guest
9043 clones, cloning guests and changing registry/UUID/hostname info, and
9044 much else besides.
9045
9046 Libguestfs uses Linux kernel and qemu code, and can access any type of
9047 guest filesystem that Linux and qemu can, including but not limited
9048 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9049 schemes, qcow, qcow2, vmdk.
9050
9051 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9052 LVs, what filesystem is in each LV, etc.).  It can also run commands
9053 in the context of the guest.  Also you can access filesystems over
9054 FUSE.
9055
9056 Errors which happen while using the API are turned into Python
9057 RuntimeError exceptions.
9058
9059 To create a guestfs handle you usually have to perform the following
9060 sequence of calls:
9061
9062 # Create the handle, call add_drive at least once, and possibly
9063 # several times if the guest has multiple block devices:
9064 g = guestfs.GuestFS ()
9065 g.add_drive (\"guest.img\")
9066
9067 # Launch the qemu subprocess and wait for it to become ready:
9068 g.launch ()
9069
9070 # Now you can issue commands, for example:
9071 logvols = g.lvs ()
9072
9073 \"\"\"
9074
9075 import libguestfsmod
9076
9077 class GuestFS:
9078     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9079
9080     def __init__ (self):
9081         \"\"\"Create a new libguestfs handle.\"\"\"
9082         self._o = libguestfsmod.create ()
9083
9084     def __del__ (self):
9085         libguestfsmod.close (self._o)
9086
9087 ";
9088
9089   List.iter (
9090     fun (name, style, _, flags, _, _, longdesc) ->
9091       pr "    def %s " name;
9092       generate_py_call_args ~handle:"self" (snd style);
9093       pr ":\n";
9094
9095       if not (List.mem NotInDocs flags) then (
9096         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9097         let doc =
9098           match fst style with
9099           | RErr | RInt _ | RInt64 _ | RBool _
9100           | RConstOptString _ | RConstString _
9101           | RString _ | RBufferOut _ -> doc
9102           | RStringList _ ->
9103               doc ^ "\n\nThis function returns a list of strings."
9104           | RStruct (_, typ) ->
9105               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9106           | RStructList (_, typ) ->
9107               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9108           | RHashtable _ ->
9109               doc ^ "\n\nThis function returns a dictionary." in
9110         let doc =
9111           if List.mem ProtocolLimitWarning flags then
9112             doc ^ "\n\n" ^ protocol_limit_warning
9113           else doc in
9114         let doc =
9115           if List.mem DangerWillRobinson flags then
9116             doc ^ "\n\n" ^ danger_will_robinson
9117           else doc in
9118         let doc =
9119           match deprecation_notice flags with
9120           | None -> doc
9121           | Some txt -> doc ^ "\n\n" ^ txt in
9122         let doc = pod2text ~width:60 name doc in
9123         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9124         let doc = String.concat "\n        " doc in
9125         pr "        u\"\"\"%s\"\"\"\n" doc;
9126       );
9127       pr "        return libguestfsmod.%s " name;
9128       generate_py_call_args ~handle:"self._o" (snd style);
9129       pr "\n";
9130       pr "\n";
9131   ) all_functions
9132
9133 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9134 and generate_py_call_args ~handle args =
9135   pr "(%s" handle;
9136   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9137   pr ")"
9138
9139 (* Useful if you need the longdesc POD text as plain text.  Returns a
9140  * list of lines.
9141  *
9142  * Because this is very slow (the slowest part of autogeneration),
9143  * we memoize the results.
9144  *)
9145 and pod2text ~width name longdesc =
9146   let key = width, name, longdesc in
9147   try Hashtbl.find pod2text_memo key
9148   with Not_found ->
9149     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9150     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9151     close_out chan;
9152     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9153     let chan = open_process_in cmd in
9154     let lines = ref [] in
9155     let rec loop i =
9156       let line = input_line chan in
9157       if i = 1 then             (* discard the first line of output *)
9158         loop (i+1)
9159       else (
9160         let line = triml line in
9161         lines := line :: !lines;
9162         loop (i+1)
9163       ) in
9164     let lines = try loop 1 with End_of_file -> List.rev !lines in
9165     unlink filename;
9166     (match close_process_in chan with
9167      | WEXITED 0 -> ()
9168      | WEXITED i ->
9169          failwithf "pod2text: process exited with non-zero status (%d)" i
9170      | WSIGNALED i | WSTOPPED i ->
9171          failwithf "pod2text: process signalled or stopped by signal %d" i
9172     );
9173     Hashtbl.add pod2text_memo key lines;
9174     pod2text_memo_updated ();
9175     lines
9176
9177 (* Generate ruby bindings. *)
9178 and generate_ruby_c () =
9179   generate_header CStyle LGPLv2plus;
9180
9181   pr "\
9182 #include <stdio.h>
9183 #include <stdlib.h>
9184
9185 #include <ruby.h>
9186
9187 #include \"guestfs.h\"
9188
9189 #include \"extconf.h\"
9190
9191 /* For Ruby < 1.9 */
9192 #ifndef RARRAY_LEN
9193 #define RARRAY_LEN(r) (RARRAY((r))->len)
9194 #endif
9195
9196 static VALUE m_guestfs;                 /* guestfs module */
9197 static VALUE c_guestfs;                 /* guestfs_h handle */
9198 static VALUE e_Error;                   /* used for all errors */
9199
9200 static void ruby_guestfs_free (void *p)
9201 {
9202   if (!p) return;
9203   guestfs_close ((guestfs_h *) p);
9204 }
9205
9206 static VALUE ruby_guestfs_create (VALUE m)
9207 {
9208   guestfs_h *g;
9209
9210   g = guestfs_create ();
9211   if (!g)
9212     rb_raise (e_Error, \"failed to create guestfs handle\");
9213
9214   /* Don't print error messages to stderr by default. */
9215   guestfs_set_error_handler (g, NULL, NULL);
9216
9217   /* Wrap it, and make sure the close function is called when the
9218    * handle goes away.
9219    */
9220   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9221 }
9222
9223 static VALUE ruby_guestfs_close (VALUE gv)
9224 {
9225   guestfs_h *g;
9226   Data_Get_Struct (gv, guestfs_h, g);
9227
9228   ruby_guestfs_free (g);
9229   DATA_PTR (gv) = NULL;
9230
9231   return Qnil;
9232 }
9233
9234 ";
9235
9236   List.iter (
9237     fun (name, style, _, _, _, _, _) ->
9238       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9239       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9240       pr ")\n";
9241       pr "{\n";
9242       pr "  guestfs_h *g;\n";
9243       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9244       pr "  if (!g)\n";
9245       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9246         name;
9247       pr "\n";
9248
9249       List.iter (
9250         function
9251         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9252             pr "  Check_Type (%sv, T_STRING);\n" n;
9253             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9254             pr "  if (!%s)\n" n;
9255             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9256             pr "              \"%s\", \"%s\");\n" n name
9257         | OptString n ->
9258             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9259         | StringList n | DeviceList n ->
9260             pr "  char **%s;\n" n;
9261             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9262             pr "  {\n";
9263             pr "    int i, len;\n";
9264             pr "    len = RARRAY_LEN (%sv);\n" n;
9265             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9266               n;
9267             pr "    for (i = 0; i < len; ++i) {\n";
9268             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9269             pr "      %s[i] = StringValueCStr (v);\n" n;
9270             pr "    }\n";
9271             pr "    %s[len] = NULL;\n" n;
9272             pr "  }\n";
9273         | Bool n ->
9274             pr "  int %s = RTEST (%sv);\n" n n
9275         | Int n ->
9276             pr "  int %s = NUM2INT (%sv);\n" n n
9277         | Int64 n ->
9278             pr "  long long %s = NUM2LL (%sv);\n" n n
9279       ) (snd style);
9280       pr "\n";
9281
9282       let error_code =
9283         match fst style with
9284         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9285         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9286         | RConstString _ | RConstOptString _ ->
9287             pr "  const char *r;\n"; "NULL"
9288         | RString _ -> pr "  char *r;\n"; "NULL"
9289         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9290         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9291         | RStructList (_, typ) ->
9292             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9293         | RBufferOut _ ->
9294             pr "  char *r;\n";
9295             pr "  size_t size;\n";
9296             "NULL" in
9297       pr "\n";
9298
9299       pr "  r = guestfs_%s " name;
9300       generate_c_call_args ~handle:"g" style;
9301       pr ";\n";
9302
9303       List.iter (
9304         function
9305         | Pathname _ | Device _ | Dev_or_Path _ | String _
9306         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9307         | StringList n | DeviceList n ->
9308             pr "  free (%s);\n" n
9309       ) (snd style);
9310
9311       pr "  if (r == %s)\n" error_code;
9312       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9313       pr "\n";
9314
9315       (match fst style with
9316        | RErr ->
9317            pr "  return Qnil;\n"
9318        | RInt _ | RBool _ ->
9319            pr "  return INT2NUM (r);\n"
9320        | RInt64 _ ->
9321            pr "  return ULL2NUM (r);\n"
9322        | RConstString _ ->
9323            pr "  return rb_str_new2 (r);\n";
9324        | RConstOptString _ ->
9325            pr "  if (r)\n";
9326            pr "    return rb_str_new2 (r);\n";
9327            pr "  else\n";
9328            pr "    return Qnil;\n";
9329        | RString _ ->
9330            pr "  VALUE rv = rb_str_new2 (r);\n";
9331            pr "  free (r);\n";
9332            pr "  return rv;\n";
9333        | RStringList _ ->
9334            pr "  int i, len = 0;\n";
9335            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9336            pr "  VALUE rv = rb_ary_new2 (len);\n";
9337            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9338            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9339            pr "    free (r[i]);\n";
9340            pr "  }\n";
9341            pr "  free (r);\n";
9342            pr "  return rv;\n"
9343        | RStruct (_, typ) ->
9344            let cols = cols_of_struct typ in
9345            generate_ruby_struct_code typ cols
9346        | RStructList (_, typ) ->
9347            let cols = cols_of_struct typ in
9348            generate_ruby_struct_list_code typ cols
9349        | RHashtable _ ->
9350            pr "  VALUE rv = rb_hash_new ();\n";
9351            pr "  int i;\n";
9352            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9353            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9354            pr "    free (r[i]);\n";
9355            pr "    free (r[i+1]);\n";
9356            pr "  }\n";
9357            pr "  free (r);\n";
9358            pr "  return rv;\n"
9359        | RBufferOut _ ->
9360            pr "  VALUE rv = rb_str_new (r, size);\n";
9361            pr "  free (r);\n";
9362            pr "  return rv;\n";
9363       );
9364
9365       pr "}\n";
9366       pr "\n"
9367   ) all_functions;
9368
9369   pr "\
9370 /* Initialize the module. */
9371 void Init__guestfs ()
9372 {
9373   m_guestfs = rb_define_module (\"Guestfs\");
9374   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9375   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9376
9377   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9378   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9379
9380 ";
9381   (* Define the rest of the methods. *)
9382   List.iter (
9383     fun (name, style, _, _, _, _, _) ->
9384       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9385       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9386   ) all_functions;
9387
9388   pr "}\n"
9389
9390 (* Ruby code to return a struct. *)
9391 and generate_ruby_struct_code typ cols =
9392   pr "  VALUE rv = rb_hash_new ();\n";
9393   List.iter (
9394     function
9395     | name, FString ->
9396         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9397     | name, FBuffer ->
9398         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9399     | name, FUUID ->
9400         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9401     | name, (FBytes|FUInt64) ->
9402         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9403     | name, FInt64 ->
9404         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9405     | name, FUInt32 ->
9406         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9407     | name, FInt32 ->
9408         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9409     | name, FOptPercent ->
9410         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9411     | name, FChar -> (* XXX wrong? *)
9412         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9413   ) cols;
9414   pr "  guestfs_free_%s (r);\n" typ;
9415   pr "  return rv;\n"
9416
9417 (* Ruby code to return a struct list. *)
9418 and generate_ruby_struct_list_code typ cols =
9419   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9420   pr "  int i;\n";
9421   pr "  for (i = 0; i < r->len; ++i) {\n";
9422   pr "    VALUE hv = rb_hash_new ();\n";
9423   List.iter (
9424     function
9425     | name, FString ->
9426         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9427     | name, FBuffer ->
9428         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
9429     | name, FUUID ->
9430         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9431     | name, (FBytes|FUInt64) ->
9432         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9433     | name, FInt64 ->
9434         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9435     | name, FUInt32 ->
9436         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9437     | name, FInt32 ->
9438         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9439     | name, FOptPercent ->
9440         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9441     | name, FChar -> (* XXX wrong? *)
9442         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9443   ) cols;
9444   pr "    rb_ary_push (rv, hv);\n";
9445   pr "  }\n";
9446   pr "  guestfs_free_%s_list (r);\n" typ;
9447   pr "  return rv;\n"
9448
9449 (* Generate Java bindings GuestFS.java file. *)
9450 and generate_java_java () =
9451   generate_header CStyle LGPLv2plus;
9452
9453   pr "\
9454 package com.redhat.et.libguestfs;
9455
9456 import java.util.HashMap;
9457 import com.redhat.et.libguestfs.LibGuestFSException;
9458 import com.redhat.et.libguestfs.PV;
9459 import com.redhat.et.libguestfs.VG;
9460 import com.redhat.et.libguestfs.LV;
9461 import com.redhat.et.libguestfs.Stat;
9462 import com.redhat.et.libguestfs.StatVFS;
9463 import com.redhat.et.libguestfs.IntBool;
9464 import com.redhat.et.libguestfs.Dirent;
9465
9466 /**
9467  * The GuestFS object is a libguestfs handle.
9468  *
9469  * @author rjones
9470  */
9471 public class GuestFS {
9472   // Load the native code.
9473   static {
9474     System.loadLibrary (\"guestfs_jni\");
9475   }
9476
9477   /**
9478    * The native guestfs_h pointer.
9479    */
9480   long g;
9481
9482   /**
9483    * Create a libguestfs handle.
9484    *
9485    * @throws LibGuestFSException
9486    */
9487   public GuestFS () throws LibGuestFSException
9488   {
9489     g = _create ();
9490   }
9491   private native long _create () throws LibGuestFSException;
9492
9493   /**
9494    * Close a libguestfs handle.
9495    *
9496    * You can also leave handles to be collected by the garbage
9497    * collector, but this method ensures that the resources used
9498    * by the handle are freed up immediately.  If you call any
9499    * other methods after closing the handle, you will get an
9500    * exception.
9501    *
9502    * @throws LibGuestFSException
9503    */
9504   public void close () throws LibGuestFSException
9505   {
9506     if (g != 0)
9507       _close (g);
9508     g = 0;
9509   }
9510   private native void _close (long g) throws LibGuestFSException;
9511
9512   public void finalize () throws LibGuestFSException
9513   {
9514     close ();
9515   }
9516
9517 ";
9518
9519   List.iter (
9520     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9521       if not (List.mem NotInDocs flags); then (
9522         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9523         let doc =
9524           if List.mem ProtocolLimitWarning flags then
9525             doc ^ "\n\n" ^ protocol_limit_warning
9526           else doc in
9527         let doc =
9528           if List.mem DangerWillRobinson flags then
9529             doc ^ "\n\n" ^ danger_will_robinson
9530           else doc in
9531         let doc =
9532           match deprecation_notice flags with
9533           | None -> doc
9534           | Some txt -> doc ^ "\n\n" ^ txt in
9535         let doc = pod2text ~width:60 name doc in
9536         let doc = List.map (            (* RHBZ#501883 *)
9537           function
9538           | "" -> "<p>"
9539           | nonempty -> nonempty
9540         ) doc in
9541         let doc = String.concat "\n   * " doc in
9542
9543         pr "  /**\n";
9544         pr "   * %s\n" shortdesc;
9545         pr "   * <p>\n";
9546         pr "   * %s\n" doc;
9547         pr "   * @throws LibGuestFSException\n";
9548         pr "   */\n";
9549         pr "  ";
9550       );
9551       generate_java_prototype ~public:true ~semicolon:false name style;
9552       pr "\n";
9553       pr "  {\n";
9554       pr "    if (g == 0)\n";
9555       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9556         name;
9557       pr "    ";
9558       if fst style <> RErr then pr "return ";
9559       pr "_%s " name;
9560       generate_java_call_args ~handle:"g" (snd style);
9561       pr ";\n";
9562       pr "  }\n";
9563       pr "  ";
9564       generate_java_prototype ~privat:true ~native:true name style;
9565       pr "\n";
9566       pr "\n";
9567   ) all_functions;
9568
9569   pr "}\n"
9570
9571 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9572 and generate_java_call_args ~handle args =
9573   pr "(%s" handle;
9574   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9575   pr ")"
9576
9577 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9578     ?(semicolon=true) name style =
9579   if privat then pr "private ";
9580   if public then pr "public ";
9581   if native then pr "native ";
9582
9583   (* return type *)
9584   (match fst style with
9585    | RErr -> pr "void ";
9586    | RInt _ -> pr "int ";
9587    | RInt64 _ -> pr "long ";
9588    | RBool _ -> pr "boolean ";
9589    | RConstString _ | RConstOptString _ | RString _
9590    | RBufferOut _ -> pr "String ";
9591    | RStringList _ -> pr "String[] ";
9592    | RStruct (_, typ) ->
9593        let name = java_name_of_struct typ in
9594        pr "%s " name;
9595    | RStructList (_, typ) ->
9596        let name = java_name_of_struct typ in
9597        pr "%s[] " name;
9598    | RHashtable _ -> pr "HashMap<String,String> ";
9599   );
9600
9601   if native then pr "_%s " name else pr "%s " name;
9602   pr "(";
9603   let needs_comma = ref false in
9604   if native then (
9605     pr "long g";
9606     needs_comma := true
9607   );
9608
9609   (* args *)
9610   List.iter (
9611     fun arg ->
9612       if !needs_comma then pr ", ";
9613       needs_comma := true;
9614
9615       match arg with
9616       | Pathname n
9617       | Device n | Dev_or_Path n
9618       | String n
9619       | OptString n
9620       | FileIn n
9621       | FileOut n ->
9622           pr "String %s" n
9623       | StringList n | DeviceList n ->
9624           pr "String[] %s" n
9625       | Bool n ->
9626           pr "boolean %s" n
9627       | Int n ->
9628           pr "int %s" n
9629       | Int64 n ->
9630           pr "long %s" n
9631   ) (snd style);
9632
9633   pr ")\n";
9634   pr "    throws LibGuestFSException";
9635   if semicolon then pr ";"
9636
9637 and generate_java_struct jtyp cols () =
9638   generate_header CStyle LGPLv2plus;
9639
9640   pr "\
9641 package com.redhat.et.libguestfs;
9642
9643 /**
9644  * Libguestfs %s structure.
9645  *
9646  * @author rjones
9647  * @see GuestFS
9648  */
9649 public class %s {
9650 " jtyp jtyp;
9651
9652   List.iter (
9653     function
9654     | name, FString
9655     | name, FUUID
9656     | name, FBuffer -> pr "  public String %s;\n" name
9657     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9658     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9659     | name, FChar -> pr "  public char %s;\n" name
9660     | name, FOptPercent ->
9661         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9662         pr "  public float %s;\n" name
9663   ) cols;
9664
9665   pr "}\n"
9666
9667 and generate_java_c () =
9668   generate_header CStyle LGPLv2plus;
9669
9670   pr "\
9671 #include <stdio.h>
9672 #include <stdlib.h>
9673 #include <string.h>
9674
9675 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9676 #include \"guestfs.h\"
9677
9678 /* Note that this function returns.  The exception is not thrown
9679  * until after the wrapper function returns.
9680  */
9681 static void
9682 throw_exception (JNIEnv *env, const char *msg)
9683 {
9684   jclass cl;
9685   cl = (*env)->FindClass (env,
9686                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9687   (*env)->ThrowNew (env, cl, msg);
9688 }
9689
9690 JNIEXPORT jlong JNICALL
9691 Java_com_redhat_et_libguestfs_GuestFS__1create
9692   (JNIEnv *env, jobject obj)
9693 {
9694   guestfs_h *g;
9695
9696   g = guestfs_create ();
9697   if (g == NULL) {
9698     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9699     return 0;
9700   }
9701   guestfs_set_error_handler (g, NULL, NULL);
9702   return (jlong) (long) g;
9703 }
9704
9705 JNIEXPORT void JNICALL
9706 Java_com_redhat_et_libguestfs_GuestFS__1close
9707   (JNIEnv *env, jobject obj, jlong jg)
9708 {
9709   guestfs_h *g = (guestfs_h *) (long) jg;
9710   guestfs_close (g);
9711 }
9712
9713 ";
9714
9715   List.iter (
9716     fun (name, style, _, _, _, _, _) ->
9717       pr "JNIEXPORT ";
9718       (match fst style with
9719        | RErr -> pr "void ";
9720        | RInt _ -> pr "jint ";
9721        | RInt64 _ -> pr "jlong ";
9722        | RBool _ -> pr "jboolean ";
9723        | RConstString _ | RConstOptString _ | RString _
9724        | RBufferOut _ -> pr "jstring ";
9725        | RStruct _ | RHashtable _ ->
9726            pr "jobject ";
9727        | RStringList _ | RStructList _ ->
9728            pr "jobjectArray ";
9729       );
9730       pr "JNICALL\n";
9731       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9732       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9733       pr "\n";
9734       pr "  (JNIEnv *env, jobject obj, jlong jg";
9735       List.iter (
9736         function
9737         | Pathname n
9738         | Device n | Dev_or_Path n
9739         | String n
9740         | OptString n
9741         | FileIn n
9742         | FileOut n ->
9743             pr ", jstring j%s" n
9744         | StringList n | DeviceList n ->
9745             pr ", jobjectArray j%s" n
9746         | Bool n ->
9747             pr ", jboolean j%s" n
9748         | Int n ->
9749             pr ", jint j%s" n
9750         | Int64 n ->
9751             pr ", jlong j%s" n
9752       ) (snd style);
9753       pr ")\n";
9754       pr "{\n";
9755       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9756       let error_code, no_ret =
9757         match fst style with
9758         | RErr -> pr "  int r;\n"; "-1", ""
9759         | RBool _
9760         | RInt _ -> pr "  int r;\n"; "-1", "0"
9761         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9762         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9763         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9764         | RString _ ->
9765             pr "  jstring jr;\n";
9766             pr "  char *r;\n"; "NULL", "NULL"
9767         | RStringList _ ->
9768             pr "  jobjectArray jr;\n";
9769             pr "  int r_len;\n";
9770             pr "  jclass cl;\n";
9771             pr "  jstring jstr;\n";
9772             pr "  char **r;\n"; "NULL", "NULL"
9773         | RStruct (_, typ) ->
9774             pr "  jobject jr;\n";
9775             pr "  jclass cl;\n";
9776             pr "  jfieldID fl;\n";
9777             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9778         | RStructList (_, typ) ->
9779             pr "  jobjectArray jr;\n";
9780             pr "  jclass cl;\n";
9781             pr "  jfieldID fl;\n";
9782             pr "  jobject jfl;\n";
9783             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9784         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9785         | RBufferOut _ ->
9786             pr "  jstring jr;\n";
9787             pr "  char *r;\n";
9788             pr "  size_t size;\n";
9789             "NULL", "NULL" in
9790       List.iter (
9791         function
9792         | Pathname n
9793         | Device n | Dev_or_Path n
9794         | String n
9795         | OptString n
9796         | FileIn n
9797         | FileOut n ->
9798             pr "  const char *%s;\n" n
9799         | StringList n | DeviceList n ->
9800             pr "  int %s_len;\n" n;
9801             pr "  const char **%s;\n" n
9802         | Bool n
9803         | Int n ->
9804             pr "  int %s;\n" n
9805         | Int64 n ->
9806             pr "  int64_t %s;\n" n
9807       ) (snd style);
9808
9809       let needs_i =
9810         (match fst style with
9811          | RStringList _ | RStructList _ -> true
9812          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9813          | RConstOptString _
9814          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9815           List.exists (function
9816                        | StringList _ -> true
9817                        | DeviceList _ -> true
9818                        | _ -> false) (snd style) in
9819       if needs_i then
9820         pr "  int i;\n";
9821
9822       pr "\n";
9823
9824       (* Get the parameters. *)
9825       List.iter (
9826         function
9827         | Pathname n
9828         | Device n | Dev_or_Path n
9829         | String n
9830         | FileIn n
9831         | FileOut n ->
9832             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9833         | OptString n ->
9834             (* This is completely undocumented, but Java null becomes
9835              * a NULL parameter.
9836              *)
9837             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9838         | StringList n | DeviceList n ->
9839             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9840             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9841             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9842             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9843               n;
9844             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9845             pr "  }\n";
9846             pr "  %s[%s_len] = NULL;\n" n n;
9847         | Bool n
9848         | Int n
9849         | Int64 n ->
9850             pr "  %s = j%s;\n" n n
9851       ) (snd style);
9852
9853       (* Make the call. *)
9854       pr "  r = guestfs_%s " name;
9855       generate_c_call_args ~handle:"g" style;
9856       pr ";\n";
9857
9858       (* Release 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 "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9867         | OptString n ->
9868             pr "  if (j%s)\n" n;
9869             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9870         | StringList n | DeviceList n ->
9871             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9872             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9873               n;
9874             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9875             pr "  }\n";
9876             pr "  free (%s);\n" n
9877         | Bool n
9878         | Int n
9879         | Int64 n -> ()
9880       ) (snd style);
9881
9882       (* Check for errors. *)
9883       pr "  if (r == %s) {\n" error_code;
9884       pr "    throw_exception (env, guestfs_last_error (g));\n";
9885       pr "    return %s;\n" no_ret;
9886       pr "  }\n";
9887
9888       (* Return value. *)
9889       (match fst style with
9890        | RErr -> ()
9891        | RInt _ -> pr "  return (jint) r;\n"
9892        | RBool _ -> pr "  return (jboolean) r;\n"
9893        | RInt64 _ -> pr "  return (jlong) r;\n"
9894        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9895        | RConstOptString _ ->
9896            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9897        | RString _ ->
9898            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9899            pr "  free (r);\n";
9900            pr "  return jr;\n"
9901        | RStringList _ ->
9902            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9903            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9904            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9905            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9906            pr "  for (i = 0; i < r_len; ++i) {\n";
9907            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9908            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9909            pr "    free (r[i]);\n";
9910            pr "  }\n";
9911            pr "  free (r);\n";
9912            pr "  return jr;\n"
9913        | RStruct (_, typ) ->
9914            let jtyp = java_name_of_struct typ in
9915            let cols = cols_of_struct typ in
9916            generate_java_struct_return typ jtyp cols
9917        | RStructList (_, typ) ->
9918            let jtyp = java_name_of_struct typ in
9919            let cols = cols_of_struct typ in
9920            generate_java_struct_list_return typ jtyp cols
9921        | RHashtable _ ->
9922            (* XXX *)
9923            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9924            pr "  return NULL;\n"
9925        | RBufferOut _ ->
9926            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9927            pr "  free (r);\n";
9928            pr "  return jr;\n"
9929       );
9930
9931       pr "}\n";
9932       pr "\n"
9933   ) all_functions
9934
9935 and generate_java_struct_return typ jtyp cols =
9936   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9937   pr "  jr = (*env)->AllocObject (env, cl);\n";
9938   List.iter (
9939     function
9940     | name, FString ->
9941         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9942         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9943     | name, FUUID ->
9944         pr "  {\n";
9945         pr "    char s[33];\n";
9946         pr "    memcpy (s, r->%s, 32);\n" name;
9947         pr "    s[32] = 0;\n";
9948         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9949         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9950         pr "  }\n";
9951     | name, FBuffer ->
9952         pr "  {\n";
9953         pr "    int len = r->%s_len;\n" name;
9954         pr "    char s[len+1];\n";
9955         pr "    memcpy (s, r->%s, len);\n" name;
9956         pr "    s[len] = 0;\n";
9957         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9958         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9959         pr "  }\n";
9960     | name, (FBytes|FUInt64|FInt64) ->
9961         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9962         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9963     | name, (FUInt32|FInt32) ->
9964         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9965         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9966     | name, FOptPercent ->
9967         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9968         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9969     | name, FChar ->
9970         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9971         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9972   ) cols;
9973   pr "  free (r);\n";
9974   pr "  return jr;\n"
9975
9976 and generate_java_struct_list_return typ jtyp cols =
9977   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9978   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9979   pr "  for (i = 0; i < r->len; ++i) {\n";
9980   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9981   List.iter (
9982     function
9983     | name, FString ->
9984         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9985         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9986     | name, FUUID ->
9987         pr "    {\n";
9988         pr "      char s[33];\n";
9989         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9990         pr "      s[32] = 0;\n";
9991         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9992         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9993         pr "    }\n";
9994     | name, FBuffer ->
9995         pr "    {\n";
9996         pr "      int len = r->val[i].%s_len;\n" name;
9997         pr "      char s[len+1];\n";
9998         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9999         pr "      s[len] = 0;\n";
10000         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10001         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10002         pr "    }\n";
10003     | name, (FBytes|FUInt64|FInt64) ->
10004         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10005         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10006     | name, (FUInt32|FInt32) ->
10007         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10008         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10009     | name, FOptPercent ->
10010         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10011         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10012     | name, FChar ->
10013         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10014         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10015   ) cols;
10016   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10017   pr "  }\n";
10018   pr "  guestfs_free_%s_list (r);\n" typ;
10019   pr "  return jr;\n"
10020
10021 and generate_java_makefile_inc () =
10022   generate_header HashStyle GPLv2plus;
10023
10024   pr "java_built_sources = \\\n";
10025   List.iter (
10026     fun (typ, jtyp) ->
10027         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10028   ) java_structs;
10029   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10030
10031 and generate_haskell_hs () =
10032   generate_header HaskellStyle LGPLv2plus;
10033
10034   (* XXX We only know how to generate partial FFI for Haskell
10035    * at the moment.  Please help out!
10036    *)
10037   let can_generate style =
10038     match style with
10039     | RErr, _
10040     | RInt _, _
10041     | RInt64 _, _ -> true
10042     | RBool _, _
10043     | RConstString _, _
10044     | RConstOptString _, _
10045     | RString _, _
10046     | RStringList _, _
10047     | RStruct _, _
10048     | RStructList _, _
10049     | RHashtable _, _
10050     | RBufferOut _, _ -> false in
10051
10052   pr "\
10053 {-# INCLUDE <guestfs.h> #-}
10054 {-# LANGUAGE ForeignFunctionInterface #-}
10055
10056 module Guestfs (
10057   create";
10058
10059   (* List out the names of the actions we want to export. *)
10060   List.iter (
10061     fun (name, style, _, _, _, _, _) ->
10062       if can_generate style then pr ",\n  %s" name
10063   ) all_functions;
10064
10065   pr "
10066   ) where
10067
10068 -- Unfortunately some symbols duplicate ones already present
10069 -- in Prelude.  We don't know which, so we hard-code a list
10070 -- here.
10071 import Prelude hiding (truncate)
10072
10073 import Foreign
10074 import Foreign.C
10075 import Foreign.C.Types
10076 import IO
10077 import Control.Exception
10078 import Data.Typeable
10079
10080 data GuestfsS = GuestfsS            -- represents the opaque C struct
10081 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10082 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10083
10084 -- XXX define properly later XXX
10085 data PV = PV
10086 data VG = VG
10087 data LV = LV
10088 data IntBool = IntBool
10089 data Stat = Stat
10090 data StatVFS = StatVFS
10091 data Hashtable = Hashtable
10092
10093 foreign import ccall unsafe \"guestfs_create\" c_create
10094   :: IO GuestfsP
10095 foreign import ccall unsafe \"&guestfs_close\" c_close
10096   :: FunPtr (GuestfsP -> IO ())
10097 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10098   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10099
10100 create :: IO GuestfsH
10101 create = do
10102   p <- c_create
10103   c_set_error_handler p nullPtr nullPtr
10104   h <- newForeignPtr c_close p
10105   return h
10106
10107 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10108   :: GuestfsP -> IO CString
10109
10110 -- last_error :: GuestfsH -> IO (Maybe String)
10111 -- last_error h = do
10112 --   str <- withForeignPtr h (\\p -> c_last_error p)
10113 --   maybePeek peekCString str
10114
10115 last_error :: GuestfsH -> IO (String)
10116 last_error h = do
10117   str <- withForeignPtr h (\\p -> c_last_error p)
10118   if (str == nullPtr)
10119     then return \"no error\"
10120     else peekCString str
10121
10122 ";
10123
10124   (* Generate wrappers for each foreign function. *)
10125   List.iter (
10126     fun (name, style, _, _, _, _, _) ->
10127       if can_generate style then (
10128         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10129         pr "  :: ";
10130         generate_haskell_prototype ~handle:"GuestfsP" style;
10131         pr "\n";
10132         pr "\n";
10133         pr "%s :: " name;
10134         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10135         pr "\n";
10136         pr "%s %s = do\n" name
10137           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10138         pr "  r <- ";
10139         (* Convert pointer arguments using with* functions. *)
10140         List.iter (
10141           function
10142           | FileIn n
10143           | FileOut n
10144           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10145           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10146           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10147           | Bool _ | Int _ | Int64 _ -> ()
10148         ) (snd style);
10149         (* Convert integer arguments. *)
10150         let args =
10151           List.map (
10152             function
10153             | Bool n -> sprintf "(fromBool %s)" n
10154             | Int n -> sprintf "(fromIntegral %s)" n
10155             | Int64 n -> sprintf "(fromIntegral %s)" n
10156             | FileIn n | FileOut n
10157             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10158           ) (snd style) in
10159         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10160           (String.concat " " ("p" :: args));
10161         (match fst style with
10162          | RErr | RInt _ | RInt64 _ | RBool _ ->
10163              pr "  if (r == -1)\n";
10164              pr "    then do\n";
10165              pr "      err <- last_error h\n";
10166              pr "      fail err\n";
10167          | RConstString _ | RConstOptString _ | RString _
10168          | RStringList _ | RStruct _
10169          | RStructList _ | RHashtable _ | RBufferOut _ ->
10170              pr "  if (r == nullPtr)\n";
10171              pr "    then do\n";
10172              pr "      err <- last_error h\n";
10173              pr "      fail err\n";
10174         );
10175         (match fst style with
10176          | RErr ->
10177              pr "    else return ()\n"
10178          | RInt _ ->
10179              pr "    else return (fromIntegral r)\n"
10180          | RInt64 _ ->
10181              pr "    else return (fromIntegral r)\n"
10182          | RBool _ ->
10183              pr "    else return (toBool r)\n"
10184          | RConstString _
10185          | RConstOptString _
10186          | RString _
10187          | RStringList _
10188          | RStruct _
10189          | RStructList _
10190          | RHashtable _
10191          | RBufferOut _ ->
10192              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10193         );
10194         pr "\n";
10195       )
10196   ) all_functions
10197
10198 and generate_haskell_prototype ~handle ?(hs = false) style =
10199   pr "%s -> " handle;
10200   let string = if hs then "String" else "CString" in
10201   let int = if hs then "Int" else "CInt" in
10202   let bool = if hs then "Bool" else "CInt" in
10203   let int64 = if hs then "Integer" else "Int64" in
10204   List.iter (
10205     fun arg ->
10206       (match arg with
10207        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10208        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10209        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10210        | Bool _ -> pr "%s" bool
10211        | Int _ -> pr "%s" int
10212        | Int64 _ -> pr "%s" int
10213        | FileIn _ -> pr "%s" string
10214        | FileOut _ -> pr "%s" string
10215       );
10216       pr " -> ";
10217   ) (snd style);
10218   pr "IO (";
10219   (match fst style with
10220    | RErr -> if not hs then pr "CInt"
10221    | RInt _ -> pr "%s" int
10222    | RInt64 _ -> pr "%s" int64
10223    | RBool _ -> pr "%s" bool
10224    | RConstString _ -> pr "%s" string
10225    | RConstOptString _ -> pr "Maybe %s" string
10226    | RString _ -> pr "%s" string
10227    | RStringList _ -> pr "[%s]" string
10228    | RStruct (_, typ) ->
10229        let name = java_name_of_struct typ in
10230        pr "%s" name
10231    | RStructList (_, typ) ->
10232        let name = java_name_of_struct typ in
10233        pr "[%s]" name
10234    | RHashtable _ -> pr "Hashtable"
10235    | RBufferOut _ -> pr "%s" string
10236   );
10237   pr ")"
10238
10239 and generate_csharp () =
10240   generate_header CPlusPlusStyle LGPLv2plus;
10241
10242   (* XXX Make this configurable by the C# assembly users. *)
10243   let library = "libguestfs.so.0" in
10244
10245   pr "\
10246 // These C# bindings are highly experimental at present.
10247 //
10248 // Firstly they only work on Linux (ie. Mono).  In order to get them
10249 // to work on Windows (ie. .Net) you would need to port the library
10250 // itself to Windows first.
10251 //
10252 // The second issue is that some calls are known to be incorrect and
10253 // can cause Mono to segfault.  Particularly: calls which pass or
10254 // return string[], or return any structure value.  This is because
10255 // we haven't worked out the correct way to do this from C#.
10256 //
10257 // The third issue is that when compiling you get a lot of warnings.
10258 // We are not sure whether the warnings are important or not.
10259 //
10260 // Fourthly we do not routinely build or test these bindings as part
10261 // of the make && make check cycle, which means that regressions might
10262 // go unnoticed.
10263 //
10264 // Suggestions and patches are welcome.
10265
10266 // To compile:
10267 //
10268 // gmcs Libguestfs.cs
10269 // mono Libguestfs.exe
10270 //
10271 // (You'll probably want to add a Test class / static main function
10272 // otherwise this won't do anything useful).
10273
10274 using System;
10275 using System.IO;
10276 using System.Runtime.InteropServices;
10277 using System.Runtime.Serialization;
10278 using System.Collections;
10279
10280 namespace Guestfs
10281 {
10282   class Error : System.ApplicationException
10283   {
10284     public Error (string message) : base (message) {}
10285     protected Error (SerializationInfo info, StreamingContext context) {}
10286   }
10287
10288   class Guestfs
10289   {
10290     IntPtr _handle;
10291
10292     [DllImport (\"%s\")]
10293     static extern IntPtr guestfs_create ();
10294
10295     public Guestfs ()
10296     {
10297       _handle = guestfs_create ();
10298       if (_handle == IntPtr.Zero)
10299         throw new Error (\"could not create guestfs handle\");
10300     }
10301
10302     [DllImport (\"%s\")]
10303     static extern void guestfs_close (IntPtr h);
10304
10305     ~Guestfs ()
10306     {
10307       guestfs_close (_handle);
10308     }
10309
10310     [DllImport (\"%s\")]
10311     static extern string guestfs_last_error (IntPtr h);
10312
10313 " library library library;
10314
10315   (* Generate C# structure bindings.  We prefix struct names with
10316    * underscore because C# cannot have conflicting struct names and
10317    * method names (eg. "class stat" and "stat").
10318    *)
10319   List.iter (
10320     fun (typ, cols) ->
10321       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10322       pr "    public class _%s {\n" typ;
10323       List.iter (
10324         function
10325         | name, FChar -> pr "      char %s;\n" name
10326         | name, FString -> pr "      string %s;\n" name
10327         | name, FBuffer ->
10328             pr "      uint %s_len;\n" name;
10329             pr "      string %s;\n" name
10330         | name, FUUID ->
10331             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10332             pr "      string %s;\n" name
10333         | name, FUInt32 -> pr "      uint %s;\n" name
10334         | name, FInt32 -> pr "      int %s;\n" name
10335         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10336         | name, FInt64 -> pr "      long %s;\n" name
10337         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10338       ) cols;
10339       pr "    }\n";
10340       pr "\n"
10341   ) structs;
10342
10343   (* Generate C# function bindings. *)
10344   List.iter (
10345     fun (name, style, _, _, _, shortdesc, _) ->
10346       let rec csharp_return_type () =
10347         match fst style with
10348         | RErr -> "void"
10349         | RBool n -> "bool"
10350         | RInt n -> "int"
10351         | RInt64 n -> "long"
10352         | RConstString n
10353         | RConstOptString n
10354         | RString n
10355         | RBufferOut n -> "string"
10356         | RStruct (_,n) -> "_" ^ n
10357         | RHashtable n -> "Hashtable"
10358         | RStringList n -> "string[]"
10359         | RStructList (_,n) -> sprintf "_%s[]" n
10360
10361       and c_return_type () =
10362         match fst style with
10363         | RErr
10364         | RBool _
10365         | RInt _ -> "int"
10366         | RInt64 _ -> "long"
10367         | RConstString _
10368         | RConstOptString _
10369         | RString _
10370         | RBufferOut _ -> "string"
10371         | RStruct (_,n) -> "_" ^ n
10372         | RHashtable _
10373         | RStringList _ -> "string[]"
10374         | RStructList (_,n) -> sprintf "_%s[]" n
10375
10376       and c_error_comparison () =
10377         match fst style with
10378         | RErr
10379         | RBool _
10380         | RInt _
10381         | RInt64 _ -> "== -1"
10382         | RConstString _
10383         | RConstOptString _
10384         | RString _
10385         | RBufferOut _
10386         | RStruct (_,_)
10387         | RHashtable _
10388         | RStringList _
10389         | RStructList (_,_) -> "== null"
10390
10391       and generate_extern_prototype () =
10392         pr "    static extern %s guestfs_%s (IntPtr h"
10393           (c_return_type ()) name;
10394         List.iter (
10395           function
10396           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10397           | FileIn n | FileOut n ->
10398               pr ", [In] string %s" n
10399           | StringList n | DeviceList n ->
10400               pr ", [In] string[] %s" n
10401           | Bool n ->
10402               pr ", bool %s" n
10403           | Int n ->
10404               pr ", int %s" n
10405           | Int64 n ->
10406               pr ", long %s" n
10407         ) (snd style);
10408         pr ");\n"
10409
10410       and generate_public_prototype () =
10411         pr "    public %s %s (" (csharp_return_type ()) name;
10412         let comma = ref false in
10413         let next () =
10414           if !comma then pr ", ";
10415           comma := true
10416         in
10417         List.iter (
10418           function
10419           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10420           | FileIn n | FileOut n ->
10421               next (); pr "string %s" n
10422           | StringList n | DeviceList n ->
10423               next (); pr "string[] %s" n
10424           | Bool n ->
10425               next (); pr "bool %s" n
10426           | Int n ->
10427               next (); pr "int %s" n
10428           | Int64 n ->
10429               next (); pr "long %s" n
10430         ) (snd style);
10431         pr ")\n"
10432
10433       and generate_call () =
10434         pr "guestfs_%s (_handle" name;
10435         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10436         pr ");\n";
10437       in
10438
10439       pr "    [DllImport (\"%s\")]\n" library;
10440       generate_extern_prototype ();
10441       pr "\n";
10442       pr "    /// <summary>\n";
10443       pr "    /// %s\n" shortdesc;
10444       pr "    /// </summary>\n";
10445       generate_public_prototype ();
10446       pr "    {\n";
10447       pr "      %s r;\n" (c_return_type ());
10448       pr "      r = ";
10449       generate_call ();
10450       pr "      if (r %s)\n" (c_error_comparison ());
10451       pr "        throw new Error (guestfs_last_error (_handle));\n";
10452       (match fst style with
10453        | RErr -> ()
10454        | RBool _ ->
10455            pr "      return r != 0 ? true : false;\n"
10456        | RHashtable _ ->
10457            pr "      Hashtable rr = new Hashtable ();\n";
10458            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10459            pr "        rr.Add (r[i], r[i+1]);\n";
10460            pr "      return rr;\n"
10461        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10462        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10463        | RStructList _ ->
10464            pr "      return r;\n"
10465       );
10466       pr "    }\n";
10467       pr "\n";
10468   ) all_functions_sorted;
10469
10470   pr "  }
10471 }
10472 "
10473
10474 and generate_bindtests () =
10475   generate_header CStyle LGPLv2plus;
10476
10477   pr "\
10478 #include <stdio.h>
10479 #include <stdlib.h>
10480 #include <inttypes.h>
10481 #include <string.h>
10482
10483 #include \"guestfs.h\"
10484 #include \"guestfs-internal.h\"
10485 #include \"guestfs-internal-actions.h\"
10486 #include \"guestfs_protocol.h\"
10487
10488 #define error guestfs_error
10489 #define safe_calloc guestfs_safe_calloc
10490 #define safe_malloc guestfs_safe_malloc
10491
10492 static void
10493 print_strings (char *const *argv)
10494 {
10495   int argc;
10496
10497   printf (\"[\");
10498   for (argc = 0; argv[argc] != NULL; ++argc) {
10499     if (argc > 0) printf (\", \");
10500     printf (\"\\\"%%s\\\"\", argv[argc]);
10501   }
10502   printf (\"]\\n\");
10503 }
10504
10505 /* The test0 function prints its parameters to stdout. */
10506 ";
10507
10508   let test0, tests =
10509     match test_functions with
10510     | [] -> assert false
10511     | test0 :: tests -> test0, tests in
10512
10513   let () =
10514     let (name, style, _, _, _, _, _) = test0 in
10515     generate_prototype ~extern:false ~semicolon:false ~newline:true
10516       ~handle:"g" ~prefix:"guestfs__" name style;
10517     pr "{\n";
10518     List.iter (
10519       function
10520       | Pathname n
10521       | Device n | Dev_or_Path n
10522       | String n
10523       | FileIn n
10524       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10525       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10526       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10527       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10528       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10529       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10530     ) (snd style);
10531     pr "  /* Java changes stdout line buffering so we need this: */\n";
10532     pr "  fflush (stdout);\n";
10533     pr "  return 0;\n";
10534     pr "}\n";
10535     pr "\n" in
10536
10537   List.iter (
10538     fun (name, style, _, _, _, _, _) ->
10539       if String.sub name (String.length name - 3) 3 <> "err" then (
10540         pr "/* Test normal return. */\n";
10541         generate_prototype ~extern:false ~semicolon:false ~newline:true
10542           ~handle:"g" ~prefix:"guestfs__" name style;
10543         pr "{\n";
10544         (match fst style with
10545          | RErr ->
10546              pr "  return 0;\n"
10547          | RInt _ ->
10548              pr "  int r;\n";
10549              pr "  sscanf (val, \"%%d\", &r);\n";
10550              pr "  return r;\n"
10551          | RInt64 _ ->
10552              pr "  int64_t r;\n";
10553              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10554              pr "  return r;\n"
10555          | RBool _ ->
10556              pr "  return STREQ (val, \"true\");\n"
10557          | RConstString _
10558          | RConstOptString _ ->
10559              (* Can't return the input string here.  Return a static
10560               * string so we ensure we get a segfault if the caller
10561               * tries to free it.
10562               *)
10563              pr "  return \"static string\";\n"
10564          | RString _ ->
10565              pr "  return strdup (val);\n"
10566          | RStringList _ ->
10567              pr "  char **strs;\n";
10568              pr "  int n, i;\n";
10569              pr "  sscanf (val, \"%%d\", &n);\n";
10570              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10571              pr "  for (i = 0; i < n; ++i) {\n";
10572              pr "    strs[i] = safe_malloc (g, 16);\n";
10573              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10574              pr "  }\n";
10575              pr "  strs[n] = NULL;\n";
10576              pr "  return strs;\n"
10577          | RStruct (_, typ) ->
10578              pr "  struct guestfs_%s *r;\n" typ;
10579              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10580              pr "  return r;\n"
10581          | RStructList (_, typ) ->
10582              pr "  struct guestfs_%s_list *r;\n" typ;
10583              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10584              pr "  sscanf (val, \"%%d\", &r->len);\n";
10585              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10586              pr "  return r;\n"
10587          | RHashtable _ ->
10588              pr "  char **strs;\n";
10589              pr "  int n, i;\n";
10590              pr "  sscanf (val, \"%%d\", &n);\n";
10591              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10592              pr "  for (i = 0; i < n; ++i) {\n";
10593              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10594              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10595              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10596              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10597              pr "  }\n";
10598              pr "  strs[n*2] = NULL;\n";
10599              pr "  return strs;\n"
10600          | RBufferOut _ ->
10601              pr "  return strdup (val);\n"
10602         );
10603         pr "}\n";
10604         pr "\n"
10605       ) else (
10606         pr "/* Test error return. */\n";
10607         generate_prototype ~extern:false ~semicolon:false ~newline:true
10608           ~handle:"g" ~prefix:"guestfs__" name style;
10609         pr "{\n";
10610         pr "  error (g, \"error\");\n";
10611         (match fst style with
10612          | RErr | RInt _ | RInt64 _ | RBool _ ->
10613              pr "  return -1;\n"
10614          | RConstString _ | RConstOptString _
10615          | RString _ | RStringList _ | RStruct _
10616          | RStructList _
10617          | RHashtable _
10618          | RBufferOut _ ->
10619              pr "  return NULL;\n"
10620         );
10621         pr "}\n";
10622         pr "\n"
10623       )
10624   ) tests
10625
10626 and generate_ocaml_bindtests () =
10627   generate_header OCamlStyle GPLv2plus;
10628
10629   pr "\
10630 let () =
10631   let g = Guestfs.create () in
10632 ";
10633
10634   let mkargs args =
10635     String.concat " " (
10636       List.map (
10637         function
10638         | CallString s -> "\"" ^ s ^ "\""
10639         | CallOptString None -> "None"
10640         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10641         | CallStringList xs ->
10642             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10643         | CallInt i when i >= 0 -> string_of_int i
10644         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10645         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10646         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10647         | CallBool b -> string_of_bool b
10648       ) args
10649     )
10650   in
10651
10652   generate_lang_bindtests (
10653     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10654   );
10655
10656   pr "print_endline \"EOF\"\n"
10657
10658 and generate_perl_bindtests () =
10659   pr "#!/usr/bin/perl -w\n";
10660   generate_header HashStyle GPLv2plus;
10661
10662   pr "\
10663 use strict;
10664
10665 use Sys::Guestfs;
10666
10667 my $g = Sys::Guestfs->new ();
10668 ";
10669
10670   let mkargs args =
10671     String.concat ", " (
10672       List.map (
10673         function
10674         | CallString s -> "\"" ^ s ^ "\""
10675         | CallOptString None -> "undef"
10676         | CallOptString (Some s) -> sprintf "\"%s\"" s
10677         | CallStringList xs ->
10678             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10679         | CallInt i -> string_of_int i
10680         | CallInt64 i -> Int64.to_string i
10681         | CallBool b -> if b then "1" else "0"
10682       ) args
10683     )
10684   in
10685
10686   generate_lang_bindtests (
10687     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10688   );
10689
10690   pr "print \"EOF\\n\"\n"
10691
10692 and generate_python_bindtests () =
10693   generate_header HashStyle GPLv2plus;
10694
10695   pr "\
10696 import guestfs
10697
10698 g = guestfs.GuestFS ()
10699 ";
10700
10701   let mkargs args =
10702     String.concat ", " (
10703       List.map (
10704         function
10705         | CallString s -> "\"" ^ s ^ "\""
10706         | CallOptString None -> "None"
10707         | CallOptString (Some s) -> sprintf "\"%s\"" s
10708         | CallStringList xs ->
10709             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10710         | CallInt i -> string_of_int i
10711         | CallInt64 i -> Int64.to_string i
10712         | CallBool b -> if b then "1" else "0"
10713       ) args
10714     )
10715   in
10716
10717   generate_lang_bindtests (
10718     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10719   );
10720
10721   pr "print \"EOF\"\n"
10722
10723 and generate_ruby_bindtests () =
10724   generate_header HashStyle GPLv2plus;
10725
10726   pr "\
10727 require 'guestfs'
10728
10729 g = Guestfs::create()
10730 ";
10731
10732   let mkargs args =
10733     String.concat ", " (
10734       List.map (
10735         function
10736         | CallString s -> "\"" ^ s ^ "\""
10737         | CallOptString None -> "nil"
10738         | CallOptString (Some s) -> sprintf "\"%s\"" s
10739         | CallStringList xs ->
10740             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10741         | CallInt i -> string_of_int i
10742         | CallInt64 i -> Int64.to_string i
10743         | CallBool b -> string_of_bool b
10744       ) args
10745     )
10746   in
10747
10748   generate_lang_bindtests (
10749     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10750   );
10751
10752   pr "print \"EOF\\n\"\n"
10753
10754 and generate_java_bindtests () =
10755   generate_header CStyle GPLv2plus;
10756
10757   pr "\
10758 import com.redhat.et.libguestfs.*;
10759
10760 public class Bindtests {
10761     public static void main (String[] argv)
10762     {
10763         try {
10764             GuestFS g = new GuestFS ();
10765 ";
10766
10767   let mkargs args =
10768     String.concat ", " (
10769       List.map (
10770         function
10771         | CallString s -> "\"" ^ s ^ "\""
10772         | CallOptString None -> "null"
10773         | CallOptString (Some s) -> sprintf "\"%s\"" s
10774         | CallStringList xs ->
10775             "new String[]{" ^
10776               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10777         | CallInt i -> string_of_int i
10778         | CallInt64 i -> Int64.to_string i
10779         | CallBool b -> string_of_bool b
10780       ) args
10781     )
10782   in
10783
10784   generate_lang_bindtests (
10785     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10786   );
10787
10788   pr "
10789             System.out.println (\"EOF\");
10790         }
10791         catch (Exception exn) {
10792             System.err.println (exn);
10793             System.exit (1);
10794         }
10795     }
10796 }
10797 "
10798
10799 and generate_haskell_bindtests () =
10800   generate_header HaskellStyle GPLv2plus;
10801
10802   pr "\
10803 module Bindtests where
10804 import qualified Guestfs
10805
10806 main = do
10807   g <- Guestfs.create
10808 ";
10809
10810   let mkargs args =
10811     String.concat " " (
10812       List.map (
10813         function
10814         | CallString s -> "\"" ^ s ^ "\""
10815         | CallOptString None -> "Nothing"
10816         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10817         | CallStringList xs ->
10818             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10819         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10820         | CallInt i -> string_of_int i
10821         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10822         | CallInt64 i -> Int64.to_string i
10823         | CallBool true -> "True"
10824         | CallBool false -> "False"
10825       ) args
10826     )
10827   in
10828
10829   generate_lang_bindtests (
10830     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10831   );
10832
10833   pr "  putStrLn \"EOF\"\n"
10834
10835 (* Language-independent bindings tests - we do it this way to
10836  * ensure there is parity in testing bindings across all languages.
10837  *)
10838 and generate_lang_bindtests call =
10839   call "test0" [CallString "abc"; CallOptString (Some "def");
10840                 CallStringList []; CallBool false;
10841                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10842   call "test0" [CallString "abc"; CallOptString None;
10843                 CallStringList []; CallBool false;
10844                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10845   call "test0" [CallString ""; CallOptString (Some "def");
10846                 CallStringList []; CallBool false;
10847                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10848   call "test0" [CallString ""; CallOptString (Some "");
10849                 CallStringList []; CallBool false;
10850                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10851   call "test0" [CallString "abc"; CallOptString (Some "def");
10852                 CallStringList ["1"]; CallBool false;
10853                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10854   call "test0" [CallString "abc"; CallOptString (Some "def");
10855                 CallStringList ["1"; "2"]; CallBool false;
10856                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10857   call "test0" [CallString "abc"; CallOptString (Some "def");
10858                 CallStringList ["1"]; CallBool true;
10859                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10860   call "test0" [CallString "abc"; CallOptString (Some "def");
10861                 CallStringList ["1"]; CallBool false;
10862                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10863   call "test0" [CallString "abc"; CallOptString (Some "def");
10864                 CallStringList ["1"]; CallBool false;
10865                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10866   call "test0" [CallString "abc"; CallOptString (Some "def");
10867                 CallStringList ["1"]; CallBool false;
10868                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10869   call "test0" [CallString "abc"; CallOptString (Some "def");
10870                 CallStringList ["1"]; CallBool false;
10871                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10872   call "test0" [CallString "abc"; CallOptString (Some "def");
10873                 CallStringList ["1"]; CallBool false;
10874                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10875   call "test0" [CallString "abc"; CallOptString (Some "def");
10876                 CallStringList ["1"]; CallBool false;
10877                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10878
10879 (* XXX Add here tests of the return and error functions. *)
10880
10881 (* Code to generator bindings for virt-inspector.  Currently only
10882  * implemented for OCaml code (for virt-p2v 2.0).
10883  *)
10884 let rng_input = "inspector/virt-inspector.rng"
10885
10886 (* Read the input file and parse it into internal structures.  This is
10887  * by no means a complete RELAX NG parser, but is just enough to be
10888  * able to parse the specific input file.
10889  *)
10890 type rng =
10891   | Element of string * rng list        (* <element name=name/> *)
10892   | Attribute of string * rng list        (* <attribute name=name/> *)
10893   | Interleave of rng list                (* <interleave/> *)
10894   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10895   | OneOrMore of rng                        (* <oneOrMore/> *)
10896   | Optional of rng                        (* <optional/> *)
10897   | Choice of string list                (* <choice><value/>*</choice> *)
10898   | Value of string                        (* <value>str</value> *)
10899   | Text                                (* <text/> *)
10900
10901 let rec string_of_rng = function
10902   | Element (name, xs) ->
10903       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10904   | Attribute (name, xs) ->
10905       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10906   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10907   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10908   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10909   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10910   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10911   | Value value -> "Value \"" ^ value ^ "\""
10912   | Text -> "Text"
10913
10914 and string_of_rng_list xs =
10915   String.concat ", " (List.map string_of_rng xs)
10916
10917 let rec parse_rng ?defines context = function
10918   | [] -> []
10919   | Xml.Element ("element", ["name", name], children) :: rest ->
10920       Element (name, parse_rng ?defines context children)
10921       :: parse_rng ?defines context rest
10922   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10923       Attribute (name, parse_rng ?defines context children)
10924       :: parse_rng ?defines context rest
10925   | Xml.Element ("interleave", [], children) :: rest ->
10926       Interleave (parse_rng ?defines context children)
10927       :: parse_rng ?defines context rest
10928   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10929       let rng = parse_rng ?defines context [child] in
10930       (match rng with
10931        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10932        | _ ->
10933            failwithf "%s: <zeroOrMore> contains more than one child element"
10934              context
10935       )
10936   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10937       let rng = parse_rng ?defines context [child] in
10938       (match rng with
10939        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10940        | _ ->
10941            failwithf "%s: <oneOrMore> contains more than one child element"
10942              context
10943       )
10944   | Xml.Element ("optional", [], [child]) :: rest ->
10945       let rng = parse_rng ?defines context [child] in
10946       (match rng with
10947        | [child] -> Optional child :: parse_rng ?defines context rest
10948        | _ ->
10949            failwithf "%s: <optional> contains more than one child element"
10950              context
10951       )
10952   | Xml.Element ("choice", [], children) :: rest ->
10953       let values = List.map (
10954         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10955         | _ ->
10956             failwithf "%s: can't handle anything except <value> in <choice>"
10957               context
10958       ) children in
10959       Choice values
10960       :: parse_rng ?defines context rest
10961   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10962       Value value :: parse_rng ?defines context rest
10963   | Xml.Element ("text", [], []) :: rest ->
10964       Text :: parse_rng ?defines context rest
10965   | Xml.Element ("ref", ["name", name], []) :: rest ->
10966       (* Look up the reference.  Because of limitations in this parser,
10967        * we can't handle arbitrarily nested <ref> yet.  You can only
10968        * use <ref> from inside <start>.
10969        *)
10970       (match defines with
10971        | None ->
10972            failwithf "%s: contains <ref>, but no refs are defined yet" context
10973        | Some map ->
10974            let rng = StringMap.find name map in
10975            rng @ parse_rng ?defines context rest
10976       )
10977   | x :: _ ->
10978       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10979
10980 let grammar =
10981   let xml = Xml.parse_file rng_input in
10982   match xml with
10983   | Xml.Element ("grammar", _,
10984                  Xml.Element ("start", _, gram) :: defines) ->
10985       (* The <define/> elements are referenced in the <start> section,
10986        * so build a map of those first.
10987        *)
10988       let defines = List.fold_left (
10989         fun map ->
10990           function Xml.Element ("define", ["name", name], defn) ->
10991             StringMap.add name defn map
10992           | _ ->
10993               failwithf "%s: expected <define name=name/>" rng_input
10994       ) StringMap.empty defines in
10995       let defines = StringMap.mapi parse_rng defines in
10996
10997       (* Parse the <start> clause, passing the defines. *)
10998       parse_rng ~defines "<start>" gram
10999   | _ ->
11000       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11001         rng_input
11002
11003 let name_of_field = function
11004   | Element (name, _) | Attribute (name, _)
11005   | ZeroOrMore (Element (name, _))
11006   | OneOrMore (Element (name, _))
11007   | Optional (Element (name, _)) -> name
11008   | Optional (Attribute (name, _)) -> name
11009   | Text -> (* an unnamed field in an element *)
11010       "data"
11011   | rng ->
11012       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11013
11014 (* At the moment this function only generates OCaml types.  However we
11015  * should parameterize it later so it can generate types/structs in a
11016  * variety of languages.
11017  *)
11018 let generate_types xs =
11019   (* A simple type is one that can be printed out directly, eg.
11020    * "string option".  A complex type is one which has a name and has
11021    * to be defined via another toplevel definition, eg. a struct.
11022    *
11023    * generate_type generates code for either simple or complex types.
11024    * In the simple case, it returns the string ("string option").  In
11025    * the complex case, it returns the name ("mountpoint").  In the
11026    * complex case it has to print out the definition before returning,
11027    * so it should only be called when we are at the beginning of a
11028    * new line (BOL context).
11029    *)
11030   let rec generate_type = function
11031     | Text ->                                (* string *)
11032         "string", true
11033     | Choice values ->                        (* [`val1|`val2|...] *)
11034         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11035     | ZeroOrMore rng ->                        (* <rng> list *)
11036         let t, is_simple = generate_type rng in
11037         t ^ " list (* 0 or more *)", is_simple
11038     | OneOrMore rng ->                        (* <rng> list *)
11039         let t, is_simple = generate_type rng in
11040         t ^ " list (* 1 or more *)", is_simple
11041                                         (* virt-inspector hack: bool *)
11042     | Optional (Attribute (name, [Value "1"])) ->
11043         "bool", true
11044     | Optional rng ->                        (* <rng> list *)
11045         let t, is_simple = generate_type rng in
11046         t ^ " option", is_simple
11047                                         (* type name = { fields ... } *)
11048     | Element (name, fields) when is_attrs_interleave fields ->
11049         generate_type_struct name (get_attrs_interleave fields)
11050     | Element (name, [field])                (* type name = field *)
11051     | Attribute (name, [field]) ->
11052         let t, is_simple = generate_type field in
11053         if is_simple then (t, true)
11054         else (
11055           pr "type %s = %s\n" name t;
11056           name, false
11057         )
11058     | Element (name, fields) ->              (* type name = { fields ... } *)
11059         generate_type_struct name fields
11060     | rng ->
11061         failwithf "generate_type failed at: %s" (string_of_rng rng)
11062
11063   and is_attrs_interleave = function
11064     | [Interleave _] -> true
11065     | Attribute _ :: fields -> is_attrs_interleave fields
11066     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11067     | _ -> false
11068
11069   and get_attrs_interleave = function
11070     | [Interleave fields] -> fields
11071     | ((Attribute _) as field) :: fields
11072     | ((Optional (Attribute _)) as field) :: fields ->
11073         field :: get_attrs_interleave fields
11074     | _ -> assert false
11075
11076   and generate_types xs =
11077     List.iter (fun x -> ignore (generate_type x)) xs
11078
11079   and generate_type_struct name fields =
11080     (* Calculate the types of the fields first.  We have to do this
11081      * before printing anything so we are still in BOL context.
11082      *)
11083     let types = List.map fst (List.map generate_type fields) in
11084
11085     (* Special case of a struct containing just a string and another
11086      * field.  Turn it into an assoc list.
11087      *)
11088     match types with
11089     | ["string"; other] ->
11090         let fname1, fname2 =
11091           match fields with
11092           | [f1; f2] -> name_of_field f1, name_of_field f2
11093           | _ -> assert false in
11094         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11095         name, false
11096
11097     | types ->
11098         pr "type %s = {\n" name;
11099         List.iter (
11100           fun (field, ftype) ->
11101             let fname = name_of_field field in
11102             pr "  %s_%s : %s;\n" name fname ftype
11103         ) (List.combine fields types);
11104         pr "}\n";
11105         (* Return the name of this type, and
11106          * false because it's not a simple type.
11107          *)
11108         name, false
11109   in
11110
11111   generate_types xs
11112
11113 let generate_parsers xs =
11114   (* As for generate_type above, generate_parser makes a parser for
11115    * some type, and returns the name of the parser it has generated.
11116    * Because it (may) need to print something, it should always be
11117    * called in BOL context.
11118    *)
11119   let rec generate_parser = function
11120     | Text ->                                (* string *)
11121         "string_child_or_empty"
11122     | Choice values ->                        (* [`val1|`val2|...] *)
11123         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11124           (String.concat "|"
11125              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11126     | ZeroOrMore rng ->                        (* <rng> list *)
11127         let pa = generate_parser rng in
11128         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11129     | OneOrMore rng ->                        (* <rng> list *)
11130         let pa = generate_parser rng in
11131         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11132                                         (* virt-inspector hack: bool *)
11133     | Optional (Attribute (name, [Value "1"])) ->
11134         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11135     | Optional rng ->                        (* <rng> list *)
11136         let pa = generate_parser rng in
11137         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11138                                         (* type name = { fields ... } *)
11139     | Element (name, fields) when is_attrs_interleave fields ->
11140         generate_parser_struct name (get_attrs_interleave fields)
11141     | Element (name, [field]) ->        (* type name = field *)
11142         let pa = generate_parser field in
11143         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11144         pr "let %s =\n" parser_name;
11145         pr "  %s\n" pa;
11146         pr "let parse_%s = %s\n" name parser_name;
11147         parser_name
11148     | Attribute (name, [field]) ->
11149         let pa = generate_parser field in
11150         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11151         pr "let %s =\n" parser_name;
11152         pr "  %s\n" pa;
11153         pr "let parse_%s = %s\n" name parser_name;
11154         parser_name
11155     | Element (name, fields) ->              (* type name = { fields ... } *)
11156         generate_parser_struct name ([], fields)
11157     | rng ->
11158         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11159
11160   and is_attrs_interleave = function
11161     | [Interleave _] -> true
11162     | Attribute _ :: fields -> is_attrs_interleave fields
11163     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11164     | _ -> false
11165
11166   and get_attrs_interleave = function
11167     | [Interleave fields] -> [], fields
11168     | ((Attribute _) as field) :: fields
11169     | ((Optional (Attribute _)) as field) :: fields ->
11170         let attrs, interleaves = get_attrs_interleave fields in
11171         (field :: attrs), interleaves
11172     | _ -> assert false
11173
11174   and generate_parsers xs =
11175     List.iter (fun x -> ignore (generate_parser x)) xs
11176
11177   and generate_parser_struct name (attrs, interleaves) =
11178     (* Generate parsers for the fields first.  We have to do this
11179      * before printing anything so we are still in BOL context.
11180      *)
11181     let fields = attrs @ interleaves in
11182     let pas = List.map generate_parser fields in
11183
11184     (* Generate an intermediate tuple from all the fields first.
11185      * If the type is just a string + another field, then we will
11186      * return this directly, otherwise it is turned into a record.
11187      *
11188      * RELAX NG note: This code treats <interleave> and plain lists of
11189      * fields the same.  In other words, it doesn't bother enforcing
11190      * any ordering of fields in the XML.
11191      *)
11192     pr "let parse_%s x =\n" name;
11193     pr "  let t = (\n    ";
11194     let comma = ref false in
11195     List.iter (
11196       fun x ->
11197         if !comma then pr ",\n    ";
11198         comma := true;
11199         match x with
11200         | Optional (Attribute (fname, [field])), pa ->
11201             pr "%s x" pa
11202         | Optional (Element (fname, [field])), pa ->
11203             pr "%s (optional_child %S x)" pa fname
11204         | Attribute (fname, [Text]), _ ->
11205             pr "attribute %S x" fname
11206         | (ZeroOrMore _ | OneOrMore _), pa ->
11207             pr "%s x" pa
11208         | Text, pa ->
11209             pr "%s x" pa
11210         | (field, pa) ->
11211             let fname = name_of_field field in
11212             pr "%s (child %S x)" pa fname
11213     ) (List.combine fields pas);
11214     pr "\n  ) in\n";
11215
11216     (match fields with
11217      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11218          pr "  t\n"
11219
11220      | _ ->
11221          pr "  (Obj.magic t : %s)\n" name
11222 (*
11223          List.iter (
11224            function
11225            | (Optional (Attribute (fname, [field])), pa) ->
11226                pr "  %s_%s =\n" name fname;
11227                pr "    %s x;\n" pa
11228            | (Optional (Element (fname, [field])), pa) ->
11229                pr "  %s_%s =\n" name fname;
11230                pr "    (let x = optional_child %S x in\n" fname;
11231                pr "     %s x);\n" pa
11232            | (field, pa) ->
11233                let fname = name_of_field field in
11234                pr "  %s_%s =\n" name fname;
11235                pr "    (let x = child %S x in\n" fname;
11236                pr "     %s x);\n" pa
11237          ) (List.combine fields pas);
11238          pr "}\n"
11239 *)
11240     );
11241     sprintf "parse_%s" name
11242   in
11243
11244   generate_parsers xs
11245
11246 (* Generate ocaml/guestfs_inspector.mli. *)
11247 let generate_ocaml_inspector_mli () =
11248   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11249
11250   pr "\
11251 (** This is an OCaml language binding to the external [virt-inspector]
11252     program.
11253
11254     For more information, please read the man page [virt-inspector(1)].
11255 *)
11256
11257 ";
11258
11259   generate_types grammar;
11260   pr "(** The nested information returned from the {!inspect} function. *)\n";
11261   pr "\n";
11262
11263   pr "\
11264 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11265 (** To inspect a libvirt domain called [name], pass a singleton
11266     list: [inspect [name]].  When using libvirt only, you may
11267     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11268
11269     To inspect a disk image or images, pass a list of the filenames
11270     of the disk images: [inspect filenames]
11271
11272     This function inspects the given guest or disk images and
11273     returns a list of operating system(s) found and a large amount
11274     of information about them.  In the vast majority of cases,
11275     a virtual machine only contains a single operating system.
11276
11277     If the optional [~xml] parameter is given, then this function
11278     skips running the external virt-inspector program and just
11279     parses the given XML directly (which is expected to be XML
11280     produced from a previous run of virt-inspector).  The list of
11281     names and connect URI are ignored in this case.
11282
11283     This function can throw a wide variety of exceptions, for example
11284     if the external virt-inspector program cannot be found, or if
11285     it doesn't generate valid XML.
11286 *)
11287 "
11288
11289 (* Generate ocaml/guestfs_inspector.ml. *)
11290 let generate_ocaml_inspector_ml () =
11291   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11292
11293   pr "open Unix\n";
11294   pr "\n";
11295
11296   generate_types grammar;
11297   pr "\n";
11298
11299   pr "\
11300 (* Misc functions which are used by the parser code below. *)
11301 let first_child = function
11302   | Xml.Element (_, _, c::_) -> c
11303   | Xml.Element (name, _, []) ->
11304       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11305   | Xml.PCData str ->
11306       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11307
11308 let string_child_or_empty = function
11309   | Xml.Element (_, _, [Xml.PCData s]) -> s
11310   | Xml.Element (_, _, []) -> \"\"
11311   | Xml.Element (x, _, _) ->
11312       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11313                 x ^ \" instead\")
11314   | Xml.PCData str ->
11315       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11316
11317 let optional_child name xml =
11318   let children = Xml.children xml in
11319   try
11320     Some (List.find (function
11321                      | Xml.Element (n, _, _) when n = name -> true
11322                      | _ -> false) children)
11323   with
11324     Not_found -> None
11325
11326 let child name xml =
11327   match optional_child name xml with
11328   | Some c -> c
11329   | None ->
11330       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11331
11332 let attribute name xml =
11333   try Xml.attrib xml name
11334   with Xml.No_attribute _ ->
11335     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11336
11337 ";
11338
11339   generate_parsers grammar;
11340   pr "\n";
11341
11342   pr "\
11343 (* Run external virt-inspector, then use parser to parse the XML. *)
11344 let inspect ?connect ?xml names =
11345   let xml =
11346     match xml with
11347     | None ->
11348         if names = [] then invalid_arg \"inspect: no names given\";
11349         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11350           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11351           names in
11352         let cmd = List.map Filename.quote cmd in
11353         let cmd = String.concat \" \" cmd in
11354         let chan = open_process_in cmd in
11355         let xml = Xml.parse_in chan in
11356         (match close_process_in chan with
11357          | WEXITED 0 -> ()
11358          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11359          | WSIGNALED i | WSTOPPED i ->
11360              failwith (\"external virt-inspector command died or stopped on sig \" ^
11361                        string_of_int i)
11362         );
11363         xml
11364     | Some doc ->
11365         Xml.parse_string doc in
11366   parse_operatingsystems xml
11367 "
11368
11369 (* This is used to generate the src/MAX_PROC_NR file which
11370  * contains the maximum procedure number, a surrogate for the
11371  * ABI version number.  See src/Makefile.am for the details.
11372  *)
11373 and generate_max_proc_nr () =
11374   let proc_nrs = List.map (
11375     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11376   ) daemon_functions in
11377
11378   let max_proc_nr = List.fold_left max 0 proc_nrs in
11379
11380   pr "%d\n" max_proc_nr
11381
11382 let output_to filename k =
11383   let filename_new = filename ^ ".new" in
11384   chan := open_out filename_new;
11385   k ();
11386   close_out !chan;
11387   chan := Pervasives.stdout;
11388
11389   (* Is the new file different from the current file? *)
11390   if Sys.file_exists filename && files_equal filename filename_new then
11391     unlink filename_new                 (* same, so skip it *)
11392   else (
11393     (* different, overwrite old one *)
11394     (try chmod filename 0o644 with Unix_error _ -> ());
11395     rename filename_new filename;
11396     chmod filename 0o444;
11397     printf "written %s\n%!" filename;
11398   )
11399
11400 let perror msg = function
11401   | Unix_error (err, _, _) ->
11402       eprintf "%s: %s\n" msg (error_message err)
11403   | exn ->
11404       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11405
11406 (* Main program. *)
11407 let () =
11408   let lock_fd =
11409     try openfile "HACKING" [O_RDWR] 0
11410     with
11411     | Unix_error (ENOENT, _, _) ->
11412         eprintf "\
11413 You are probably running this from the wrong directory.
11414 Run it from the top source directory using the command
11415   src/generator.ml
11416 ";
11417         exit 1
11418     | exn ->
11419         perror "open: HACKING" exn;
11420         exit 1 in
11421
11422   (* Acquire a lock so parallel builds won't try to run the generator
11423    * twice at the same time.  Subsequent builds will wait for the first
11424    * one to finish.  Note the lock is released implicitly when the
11425    * program exits.
11426    *)
11427   (try lockf lock_fd F_LOCK 1
11428    with exn ->
11429      perror "lock: HACKING" exn;
11430      exit 1);
11431
11432   check_functions ();
11433
11434   output_to "src/guestfs_protocol.x" generate_xdr;
11435   output_to "src/guestfs-structs.h" generate_structs_h;
11436   output_to "src/guestfs-actions.h" generate_actions_h;
11437   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11438   output_to "src/guestfs-actions.c" generate_client_actions;
11439   output_to "src/guestfs-bindtests.c" generate_bindtests;
11440   output_to "src/guestfs-structs.pod" generate_structs_pod;
11441   output_to "src/guestfs-actions.pod" generate_actions_pod;
11442   output_to "src/guestfs-availability.pod" generate_availability_pod;
11443   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11444   output_to "src/libguestfs.syms" generate_linker_script;
11445   output_to "daemon/actions.h" generate_daemon_actions_h;
11446   output_to "daemon/stubs.c" generate_daemon_actions;
11447   output_to "daemon/names.c" generate_daemon_names;
11448   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11449   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11450   output_to "capitests/tests.c" generate_tests;
11451   output_to "fish/cmds.c" generate_fish_cmds;
11452   output_to "fish/completion.c" generate_fish_completion;
11453   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11454   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11455   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11456   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11457   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11458   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11459   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11460   output_to "perl/Guestfs.xs" generate_perl_xs;
11461   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11462   output_to "perl/bindtests.pl" generate_perl_bindtests;
11463   output_to "python/guestfs-py.c" generate_python_c;
11464   output_to "python/guestfs.py" generate_python_py;
11465   output_to "python/bindtests.py" generate_python_bindtests;
11466   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11467   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11468   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11469
11470   List.iter (
11471     fun (typ, jtyp) ->
11472       let cols = cols_of_struct typ in
11473       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11474       output_to filename (generate_java_struct jtyp cols);
11475   ) java_structs;
11476
11477   output_to "java/Makefile.inc" generate_java_makefile_inc;
11478   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11479   output_to "java/Bindtests.java" generate_java_bindtests;
11480   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11481   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11482   output_to "csharp/Libguestfs.cs" generate_csharp;
11483
11484   (* Always generate this file last, and unconditionally.  It's used
11485    * by the Makefile to know when we must re-run the generator.
11486    *)
11487   let chan = open_out "src/stamp-generator" in
11488   fprintf chan "1\n";
11489   close_out chan;
11490
11491   printf "generated %d lines of code\n" !lines