Documentation: Clarify documentation on the bootable flag.
[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 operating systems (notably
4099 Windows) to determine which partition to boot from.  It is by
4100 no means universally recognized.");
4101
4102   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4103    [InitEmpty, Always, TestRun (
4104       [["part_disk"; "/dev/sda"; "gpt"];
4105        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4106    "set partition name",
4107    "\
4108 This sets the partition name on partition numbered C<partnum> on
4109 device C<device>.  Note that partitions are numbered from 1.
4110
4111 The partition name can only be set on certain types of partition
4112 table.  This works on C<gpt> but not on C<mbr> partitions.");
4113
4114   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4115    [], (* XXX Add a regression test for this. *)
4116    "list partitions on a device",
4117    "\
4118 This command parses the partition table on C<device> and
4119 returns the list of partitions found.
4120
4121 The fields in the returned structure are:
4122
4123 =over 4
4124
4125 =item B<part_num>
4126
4127 Partition number, counting from 1.
4128
4129 =item B<part_start>
4130
4131 Start of the partition I<in bytes>.  To get sectors you have to
4132 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4133
4134 =item B<part_end>
4135
4136 End of the partition in bytes.
4137
4138 =item B<part_size>
4139
4140 Size of the partition in bytes.
4141
4142 =back");
4143
4144   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4145    [InitEmpty, Always, TestOutput (
4146       [["part_disk"; "/dev/sda"; "gpt"];
4147        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4148    "get the partition table type",
4149    "\
4150 This command examines the partition table on C<device> and
4151 returns the partition table type (format) being used.
4152
4153 Common return values include: C<msdos> (a DOS/Windows style MBR
4154 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4155 values are possible, although unusual.  See C<guestfs_part_init>
4156 for a full list.");
4157
4158   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4159    [InitBasicFS, Always, TestOutputBuffer (
4160       [["fill"; "0x63"; "10"; "/test"];
4161        ["read_file"; "/test"]], "cccccccccc")],
4162    "fill a file with octets",
4163    "\
4164 This command creates a new file called C<path>.  The initial
4165 content of the file is C<len> octets of C<c>, where C<c>
4166 must be a number in the range C<[0..255]>.
4167
4168 To fill a file with zero bytes (sparsely), it is
4169 much more efficient to use C<guestfs_truncate_size>.");
4170
4171   ("available", (RErr, [StringList "groups"]), 216, [],
4172    [InitNone, Always, TestRun [["available"; ""]]],
4173    "test availability of some parts of the API",
4174    "\
4175 This command is used to check the availability of some
4176 groups of functionality in the appliance, which not all builds of
4177 the libguestfs appliance will be able to provide.
4178
4179 The libguestfs groups, and the functions that those
4180 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4181
4182 The argument C<groups> is a list of group names, eg:
4183 C<[\"inotify\", \"augeas\"]> would check for the availability of
4184 the Linux inotify functions and Augeas (configuration file
4185 editing) functions.
4186
4187 The command returns no error if I<all> requested groups are available.
4188
4189 It fails with an error if one or more of the requested
4190 groups is unavailable in the appliance.
4191
4192 If an unknown group name is included in the
4193 list of groups then an error is always returned.
4194
4195 I<Notes:>
4196
4197 =over 4
4198
4199 =item *
4200
4201 You must call C<guestfs_launch> before calling this function.
4202
4203 The reason is because we don't know what groups are
4204 supported by the appliance/daemon until it is running and can
4205 be queried.
4206
4207 =item *
4208
4209 If a group of functions is available, this does not necessarily
4210 mean that they will work.  You still have to check for errors
4211 when calling individual API functions even if they are
4212 available.
4213
4214 =item *
4215
4216 It is usually the job of distro packagers to build
4217 complete functionality into the libguestfs appliance.
4218 Upstream libguestfs, if built from source with all
4219 requirements satisfied, will support everything.
4220
4221 =item *
4222
4223 This call was added in version C<1.0.80>.  In previous
4224 versions of libguestfs all you could do would be to speculatively
4225 execute a command to find out if the daemon implemented it.
4226 See also C<guestfs_version>.
4227
4228 =back");
4229
4230   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4231    [InitBasicFS, Always, TestOutputBuffer (
4232       [["write_file"; "/src"; "hello, world"; "0"];
4233        ["dd"; "/src"; "/dest"];
4234        ["read_file"; "/dest"]], "hello, world")],
4235    "copy from source to destination using dd",
4236    "\
4237 This command copies from one source device or file C<src>
4238 to another destination device or file C<dest>.  Normally you
4239 would use this to copy to or from a device or partition, for
4240 example to duplicate a filesystem.
4241
4242 If the destination is a device, it must be as large or larger
4243 than the source file or device, otherwise the copy will fail.
4244 This command cannot do partial copies (see C<guestfs_copy_size>).");
4245
4246   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4247    [InitBasicFS, Always, TestOutputInt (
4248       [["write_file"; "/file"; "hello, world"; "0"];
4249        ["filesize"; "/file"]], 12)],
4250    "return the size of the file in bytes",
4251    "\
4252 This command returns the size of C<file> in bytes.
4253
4254 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4255 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4256 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4257
4258   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4259    [InitBasicFSonLVM, Always, TestOutputList (
4260       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4261        ["lvs"]], ["/dev/VG/LV2"])],
4262    "rename an LVM logical volume",
4263    "\
4264 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4265
4266   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4267    [InitBasicFSonLVM, Always, TestOutputList (
4268       [["umount"; "/"];
4269        ["vg_activate"; "false"; "VG"];
4270        ["vgrename"; "VG"; "VG2"];
4271        ["vg_activate"; "true"; "VG2"];
4272        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4273        ["vgs"]], ["VG2"])],
4274    "rename an LVM volume group",
4275    "\
4276 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4277
4278   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4279    [InitISOFS, Always, TestOutputBuffer (
4280       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4281    "list the contents of a single file in an initrd",
4282    "\
4283 This command unpacks the file C<filename> from the initrd file
4284 called C<initrdpath>.  The filename must be given I<without> the
4285 initial C</> character.
4286
4287 For example, in guestfish you could use the following command
4288 to examine the boot script (usually called C</init>)
4289 contained in a Linux initrd or initramfs image:
4290
4291  initrd-cat /boot/initrd-<version>.img init
4292
4293 See also C<guestfs_initrd_list>.");
4294
4295   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4296    [],
4297    "get the UUID of a physical volume",
4298    "\
4299 This command returns the UUID of the LVM PV C<device>.");
4300
4301   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4302    [],
4303    "get the UUID of a volume group",
4304    "\
4305 This command returns the UUID of the LVM VG named C<vgname>.");
4306
4307   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4308    [],
4309    "get the UUID of a logical volume",
4310    "\
4311 This command returns the UUID of the LVM LV C<device>.");
4312
4313   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4314    [],
4315    "get the PV UUIDs containing the volume group",
4316    "\
4317 Given a VG called C<vgname>, this returns the UUIDs of all
4318 the physical volumes that this volume group resides on.
4319
4320 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4321 calls to associate physical volumes and volume groups.
4322
4323 See also C<guestfs_vglvuuids>.");
4324
4325   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4326    [],
4327    "get the LV UUIDs of all LVs in the volume group",
4328    "\
4329 Given a VG called C<vgname>, this returns the UUIDs of all
4330 the logical volumes created in this volume group.
4331
4332 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4333 calls to associate logical volumes and volume groups.
4334
4335 See also C<guestfs_vgpvuuids>.");
4336
4337   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4338    [InitBasicFS, Always, TestOutputBuffer (
4339       [["write_file"; "/src"; "hello, world"; "0"];
4340        ["copy_size"; "/src"; "/dest"; "5"];
4341        ["read_file"; "/dest"]], "hello")],
4342    "copy size bytes from source to destination using dd",
4343    "\
4344 This command copies exactly C<size> bytes from one source device
4345 or file C<src> to another destination device or file C<dest>.
4346
4347 Note this will fail if the source is too short or if the destination
4348 is not large enough.");
4349
4350   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4351    [InitBasicFSonLVM, Always, TestRun (
4352       [["zero_device"; "/dev/VG/LV"]])],
4353    "write zeroes to an entire device",
4354    "\
4355 This command writes zeroes over the entire C<device>.  Compare
4356 with C<guestfs_zero> which just zeroes the first few blocks of
4357 a device.");
4358
4359   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4360    [InitBasicFS, Always, TestOutput (
4361       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4362        ["cat"; "/hello"]], "hello\n")],
4363    "unpack compressed tarball to directory",
4364    "\
4365 This command uploads and unpacks local file C<tarball> (an
4366 I<xz compressed> tar file) into C<directory>.");
4367
4368   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4369    [],
4370    "pack directory into compressed tarball",
4371    "\
4372 This command packs the contents of C<directory> and downloads
4373 it to local file C<tarball> (as an xz compressed tar archive).");
4374
4375   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4376    [],
4377    "resize an NTFS filesystem",
4378    "\
4379 This command resizes an NTFS filesystem, expanding or
4380 shrinking it to the size of the underlying device.
4381 See also L<ntfsresize(8)>.");
4382
4383   ("vgscan", (RErr, []), 232, [],
4384    [InitEmpty, Always, TestRun (
4385       [["vgscan"]])],
4386    "rescan for LVM physical volumes, volume groups and logical volumes",
4387    "\
4388 This rescans all block devices and rebuilds the list of LVM
4389 physical volumes, volume groups and logical volumes.");
4390
4391 ]
4392
4393 let all_functions = non_daemon_functions @ daemon_functions
4394
4395 (* In some places we want the functions to be displayed sorted
4396  * alphabetically, so this is useful:
4397  *)
4398 let all_functions_sorted =
4399   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4400                compare n1 n2) all_functions
4401
4402 (* Field types for structures. *)
4403 type field =
4404   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4405   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4406   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4407   | FUInt32
4408   | FInt32
4409   | FUInt64
4410   | FInt64
4411   | FBytes                      (* Any int measure that counts bytes. *)
4412   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4413   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4414
4415 (* Because we generate extra parsing code for LVM command line tools,
4416  * we have to pull out the LVM columns separately here.
4417  *)
4418 let lvm_pv_cols = [
4419   "pv_name", FString;
4420   "pv_uuid", FUUID;
4421   "pv_fmt", FString;
4422   "pv_size", FBytes;
4423   "dev_size", FBytes;
4424   "pv_free", FBytes;
4425   "pv_used", FBytes;
4426   "pv_attr", FString (* XXX *);
4427   "pv_pe_count", FInt64;
4428   "pv_pe_alloc_count", FInt64;
4429   "pv_tags", FString;
4430   "pe_start", FBytes;
4431   "pv_mda_count", FInt64;
4432   "pv_mda_free", FBytes;
4433   (* Not in Fedora 10:
4434      "pv_mda_size", FBytes;
4435   *)
4436 ]
4437 let lvm_vg_cols = [
4438   "vg_name", FString;
4439   "vg_uuid", FUUID;
4440   "vg_fmt", FString;
4441   "vg_attr", FString (* XXX *);
4442   "vg_size", FBytes;
4443   "vg_free", FBytes;
4444   "vg_sysid", FString;
4445   "vg_extent_size", FBytes;
4446   "vg_extent_count", FInt64;
4447   "vg_free_count", FInt64;
4448   "max_lv", FInt64;
4449   "max_pv", FInt64;
4450   "pv_count", FInt64;
4451   "lv_count", FInt64;
4452   "snap_count", FInt64;
4453   "vg_seqno", FInt64;
4454   "vg_tags", FString;
4455   "vg_mda_count", FInt64;
4456   "vg_mda_free", FBytes;
4457   (* Not in Fedora 10:
4458      "vg_mda_size", FBytes;
4459   *)
4460 ]
4461 let lvm_lv_cols = [
4462   "lv_name", FString;
4463   "lv_uuid", FUUID;
4464   "lv_attr", FString (* XXX *);
4465   "lv_major", FInt64;
4466   "lv_minor", FInt64;
4467   "lv_kernel_major", FInt64;
4468   "lv_kernel_minor", FInt64;
4469   "lv_size", FBytes;
4470   "seg_count", FInt64;
4471   "origin", FString;
4472   "snap_percent", FOptPercent;
4473   "copy_percent", FOptPercent;
4474   "move_pv", FString;
4475   "lv_tags", FString;
4476   "mirror_log", FString;
4477   "modules", FString;
4478 ]
4479
4480 (* Names and fields in all structures (in RStruct and RStructList)
4481  * that we support.
4482  *)
4483 let structs = [
4484   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4485    * not use this struct in any new code.
4486    *)
4487   "int_bool", [
4488     "i", FInt32;                (* for historical compatibility *)
4489     "b", FInt32;                (* for historical compatibility *)
4490   ];
4491
4492   (* LVM PVs, VGs, LVs. *)
4493   "lvm_pv", lvm_pv_cols;
4494   "lvm_vg", lvm_vg_cols;
4495   "lvm_lv", lvm_lv_cols;
4496
4497   (* Column names and types from stat structures.
4498    * NB. Can't use things like 'st_atime' because glibc header files
4499    * define some of these as macros.  Ugh.
4500    *)
4501   "stat", [
4502     "dev", FInt64;
4503     "ino", FInt64;
4504     "mode", FInt64;
4505     "nlink", FInt64;
4506     "uid", FInt64;
4507     "gid", FInt64;
4508     "rdev", FInt64;
4509     "size", FInt64;
4510     "blksize", FInt64;
4511     "blocks", FInt64;
4512     "atime", FInt64;
4513     "mtime", FInt64;
4514     "ctime", FInt64;
4515   ];
4516   "statvfs", [
4517     "bsize", FInt64;
4518     "frsize", FInt64;
4519     "blocks", FInt64;
4520     "bfree", FInt64;
4521     "bavail", FInt64;
4522     "files", FInt64;
4523     "ffree", FInt64;
4524     "favail", FInt64;
4525     "fsid", FInt64;
4526     "flag", FInt64;
4527     "namemax", FInt64;
4528   ];
4529
4530   (* Column names in dirent structure. *)
4531   "dirent", [
4532     "ino", FInt64;
4533     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4534     "ftyp", FChar;
4535     "name", FString;
4536   ];
4537
4538   (* Version numbers. *)
4539   "version", [
4540     "major", FInt64;
4541     "minor", FInt64;
4542     "release", FInt64;
4543     "extra", FString;
4544   ];
4545
4546   (* Extended attribute. *)
4547   "xattr", [
4548     "attrname", FString;
4549     "attrval", FBuffer;
4550   ];
4551
4552   (* Inotify events. *)
4553   "inotify_event", [
4554     "in_wd", FInt64;
4555     "in_mask", FUInt32;
4556     "in_cookie", FUInt32;
4557     "in_name", FString;
4558   ];
4559
4560   (* Partition table entry. *)
4561   "partition", [
4562     "part_num", FInt32;
4563     "part_start", FBytes;
4564     "part_end", FBytes;
4565     "part_size", FBytes;
4566   ];
4567 ] (* end of structs *)
4568
4569 (* Ugh, Java has to be different ..
4570  * These names are also used by the Haskell bindings.
4571  *)
4572 let java_structs = [
4573   "int_bool", "IntBool";
4574   "lvm_pv", "PV";
4575   "lvm_vg", "VG";
4576   "lvm_lv", "LV";
4577   "stat", "Stat";
4578   "statvfs", "StatVFS";
4579   "dirent", "Dirent";
4580   "version", "Version";
4581   "xattr", "XAttr";
4582   "inotify_event", "INotifyEvent";
4583   "partition", "Partition";
4584 ]
4585
4586 (* What structs are actually returned. *)
4587 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4588
4589 (* Returns a list of RStruct/RStructList structs that are returned
4590  * by any function.  Each element of returned list is a pair:
4591  *
4592  * (structname, RStructOnly)
4593  *    == there exists function which returns RStruct (_, structname)
4594  * (structname, RStructListOnly)
4595  *    == there exists function which returns RStructList (_, structname)
4596  * (structname, RStructAndList)
4597  *    == there are functions returning both RStruct (_, structname)
4598  *                                      and RStructList (_, structname)
4599  *)
4600 let rstructs_used_by functions =
4601   (* ||| is a "logical OR" for rstructs_used_t *)
4602   let (|||) a b =
4603     match a, b with
4604     | RStructAndList, _
4605     | _, RStructAndList -> RStructAndList
4606     | RStructOnly, RStructListOnly
4607     | RStructListOnly, RStructOnly -> RStructAndList
4608     | RStructOnly, RStructOnly -> RStructOnly
4609     | RStructListOnly, RStructListOnly -> RStructListOnly
4610   in
4611
4612   let h = Hashtbl.create 13 in
4613
4614   (* if elem->oldv exists, update entry using ||| operator,
4615    * else just add elem->newv to the hash
4616    *)
4617   let update elem newv =
4618     try  let oldv = Hashtbl.find h elem in
4619          Hashtbl.replace h elem (newv ||| oldv)
4620     with Not_found -> Hashtbl.add h elem newv
4621   in
4622
4623   List.iter (
4624     fun (_, style, _, _, _, _, _) ->
4625       match fst style with
4626       | RStruct (_, structname) -> update structname RStructOnly
4627       | RStructList (_, structname) -> update structname RStructListOnly
4628       | _ -> ()
4629   ) functions;
4630
4631   (* return key->values as a list of (key,value) *)
4632   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4633
4634 (* Used for testing language bindings. *)
4635 type callt =
4636   | CallString of string
4637   | CallOptString of string option
4638   | CallStringList of string list
4639   | CallInt of int
4640   | CallInt64 of int64
4641   | CallBool of bool
4642
4643 (* Used to memoize the result of pod2text. *)
4644 let pod2text_memo_filename = "src/.pod2text.data"
4645 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4646   try
4647     let chan = open_in pod2text_memo_filename in
4648     let v = input_value chan in
4649     close_in chan;
4650     v
4651   with
4652     _ -> Hashtbl.create 13
4653 let pod2text_memo_updated () =
4654   let chan = open_out pod2text_memo_filename in
4655   output_value chan pod2text_memo;
4656   close_out chan
4657
4658 (* Useful functions.
4659  * Note we don't want to use any external OCaml libraries which
4660  * makes this a bit harder than it should be.
4661  *)
4662 module StringMap = Map.Make (String)
4663
4664 let failwithf fs = ksprintf failwith fs
4665
4666 let unique = let i = ref 0 in fun () -> incr i; !i
4667
4668 let replace_char s c1 c2 =
4669   let s2 = String.copy s in
4670   let r = ref false in
4671   for i = 0 to String.length s2 - 1 do
4672     if String.unsafe_get s2 i = c1 then (
4673       String.unsafe_set s2 i c2;
4674       r := true
4675     )
4676   done;
4677   if not !r then s else s2
4678
4679 let isspace c =
4680   c = ' '
4681   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4682
4683 let triml ?(test = isspace) str =
4684   let i = ref 0 in
4685   let n = ref (String.length str) in
4686   while !n > 0 && test str.[!i]; do
4687     decr n;
4688     incr i
4689   done;
4690   if !i = 0 then str
4691   else String.sub str !i !n
4692
4693 let trimr ?(test = isspace) str =
4694   let n = ref (String.length str) in
4695   while !n > 0 && test str.[!n-1]; do
4696     decr n
4697   done;
4698   if !n = String.length str then str
4699   else String.sub str 0 !n
4700
4701 let trim ?(test = isspace) str =
4702   trimr ~test (triml ~test str)
4703
4704 let rec find s sub =
4705   let len = String.length s in
4706   let sublen = String.length sub in
4707   let rec loop i =
4708     if i <= len-sublen then (
4709       let rec loop2 j =
4710         if j < sublen then (
4711           if s.[i+j] = sub.[j] then loop2 (j+1)
4712           else -1
4713         ) else
4714           i (* found *)
4715       in
4716       let r = loop2 0 in
4717       if r = -1 then loop (i+1) else r
4718     ) else
4719       -1 (* not found *)
4720   in
4721   loop 0
4722
4723 let rec replace_str s s1 s2 =
4724   let len = String.length s in
4725   let sublen = String.length s1 in
4726   let i = find s s1 in
4727   if i = -1 then s
4728   else (
4729     let s' = String.sub s 0 i in
4730     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4731     s' ^ s2 ^ replace_str s'' s1 s2
4732   )
4733
4734 let rec string_split sep str =
4735   let len = String.length str in
4736   let seplen = String.length sep in
4737   let i = find str sep in
4738   if i = -1 then [str]
4739   else (
4740     let s' = String.sub str 0 i in
4741     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4742     s' :: string_split sep s''
4743   )
4744
4745 let files_equal n1 n2 =
4746   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4747   match Sys.command cmd with
4748   | 0 -> true
4749   | 1 -> false
4750   | i -> failwithf "%s: failed with error code %d" cmd i
4751
4752 let rec filter_map f = function
4753   | [] -> []
4754   | x :: xs ->
4755       match f x with
4756       | Some y -> y :: filter_map f xs
4757       | None -> filter_map f xs
4758
4759 let rec find_map f = function
4760   | [] -> raise Not_found
4761   | x :: xs ->
4762       match f x with
4763       | Some y -> y
4764       | None -> find_map f xs
4765
4766 let iteri f xs =
4767   let rec loop i = function
4768     | [] -> ()
4769     | x :: xs -> f i x; loop (i+1) xs
4770   in
4771   loop 0 xs
4772
4773 let mapi f xs =
4774   let rec loop i = function
4775     | [] -> []
4776     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4777   in
4778   loop 0 xs
4779
4780 let count_chars c str =
4781   let count = ref 0 in
4782   for i = 0 to String.length str - 1 do
4783     if c = String.unsafe_get str i then incr count
4784   done;
4785   !count
4786
4787 let name_of_argt = function
4788   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4789   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4790   | FileIn n | FileOut n -> n
4791
4792 let java_name_of_struct typ =
4793   try List.assoc typ java_structs
4794   with Not_found ->
4795     failwithf
4796       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4797
4798 let cols_of_struct typ =
4799   try List.assoc typ structs
4800   with Not_found ->
4801     failwithf "cols_of_struct: unknown struct %s" typ
4802
4803 let seq_of_test = function
4804   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4805   | TestOutputListOfDevices (s, _)
4806   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4807   | TestOutputTrue s | TestOutputFalse s
4808   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4809   | TestOutputStruct (s, _)
4810   | TestLastFail s -> s
4811
4812 (* Handling for function flags. *)
4813 let protocol_limit_warning =
4814   "Because of the message protocol, there is a transfer limit
4815 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4816
4817 let danger_will_robinson =
4818   "B<This command is dangerous.  Without careful use you
4819 can easily destroy all your data>."
4820
4821 let deprecation_notice flags =
4822   try
4823     let alt =
4824       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4825     let txt =
4826       sprintf "This function is deprecated.
4827 In new code, use the C<%s> call instead.
4828
4829 Deprecated functions will not be removed from the API, but the
4830 fact that they are deprecated indicates that there are problems
4831 with correct use of these functions." alt in
4832     Some txt
4833   with
4834     Not_found -> None
4835
4836 (* Create list of optional groups. *)
4837 let optgroups =
4838   let h = Hashtbl.create 13 in
4839   List.iter (
4840     fun (name, _, _, flags, _, _, _) ->
4841       List.iter (
4842         function
4843         | Optional group ->
4844             let names = try Hashtbl.find h group with Not_found -> [] in
4845             Hashtbl.replace h group (name :: names)
4846         | _ -> ()
4847       ) flags
4848   ) daemon_functions;
4849   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4850   let groups =
4851     List.map (
4852       fun group -> group, List.sort compare (Hashtbl.find h group)
4853     ) groups in
4854   List.sort (fun x y -> compare (fst x) (fst y)) groups
4855
4856 (* Check function names etc. for consistency. *)
4857 let check_functions () =
4858   let contains_uppercase str =
4859     let len = String.length str in
4860     let rec loop i =
4861       if i >= len then false
4862       else (
4863         let c = str.[i] in
4864         if c >= 'A' && c <= 'Z' then true
4865         else loop (i+1)
4866       )
4867     in
4868     loop 0
4869   in
4870
4871   (* Check function names. *)
4872   List.iter (
4873     fun (name, _, _, _, _, _, _) ->
4874       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4875         failwithf "function name %s does not need 'guestfs' prefix" name;
4876       if name = "" then
4877         failwithf "function name is empty";
4878       if name.[0] < 'a' || name.[0] > 'z' then
4879         failwithf "function name %s must start with lowercase a-z" name;
4880       if String.contains name '-' then
4881         failwithf "function name %s should not contain '-', use '_' instead."
4882           name
4883   ) all_functions;
4884
4885   (* Check function parameter/return names. *)
4886   List.iter (
4887     fun (name, style, _, _, _, _, _) ->
4888       let check_arg_ret_name n =
4889         if contains_uppercase n then
4890           failwithf "%s param/ret %s should not contain uppercase chars"
4891             name n;
4892         if String.contains n '-' || String.contains n '_' then
4893           failwithf "%s param/ret %s should not contain '-' or '_'"
4894             name n;
4895         if n = "value" then
4896           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;
4897         if n = "int" || n = "char" || n = "short" || n = "long" then
4898           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4899         if n = "i" || n = "n" then
4900           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4901         if n = "argv" || n = "args" then
4902           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4903
4904         (* List Haskell, OCaml and C keywords here.
4905          * http://www.haskell.org/haskellwiki/Keywords
4906          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4907          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4908          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4909          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4910          * Omitting _-containing words, since they're handled above.
4911          * Omitting the OCaml reserved word, "val", is ok,
4912          * and saves us from renaming several parameters.
4913          *)
4914         let reserved = [
4915           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4916           "char"; "class"; "const"; "constraint"; "continue"; "data";
4917           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4918           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4919           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4920           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4921           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4922           "interface";
4923           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4924           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4925           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4926           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4927           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4928           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4929           "volatile"; "when"; "where"; "while";
4930           ] in
4931         if List.mem n reserved then
4932           failwithf "%s has param/ret using reserved word %s" name n;
4933       in
4934
4935       (match fst style with
4936        | RErr -> ()
4937        | RInt n | RInt64 n | RBool n
4938        | RConstString n | RConstOptString n | RString n
4939        | RStringList n | RStruct (n, _) | RStructList (n, _)
4940        | RHashtable n | RBufferOut n ->
4941            check_arg_ret_name n
4942       );
4943       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4944   ) all_functions;
4945
4946   (* Check short descriptions. *)
4947   List.iter (
4948     fun (name, _, _, _, _, shortdesc, _) ->
4949       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4950         failwithf "short description of %s should begin with lowercase." name;
4951       let c = shortdesc.[String.length shortdesc-1] in
4952       if c = '\n' || c = '.' then
4953         failwithf "short description of %s should not end with . or \\n." name
4954   ) all_functions;
4955
4956   (* Check long dscriptions. *)
4957   List.iter (
4958     fun (name, _, _, _, _, _, longdesc) ->
4959       if longdesc.[String.length longdesc-1] = '\n' then
4960         failwithf "long description of %s should not end with \\n." name
4961   ) all_functions;
4962
4963   (* Check proc_nrs. *)
4964   List.iter (
4965     fun (name, _, proc_nr, _, _, _, _) ->
4966       if proc_nr <= 0 then
4967         failwithf "daemon function %s should have proc_nr > 0" name
4968   ) daemon_functions;
4969
4970   List.iter (
4971     fun (name, _, proc_nr, _, _, _, _) ->
4972       if proc_nr <> -1 then
4973         failwithf "non-daemon function %s should have proc_nr -1" name
4974   ) non_daemon_functions;
4975
4976   let proc_nrs =
4977     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4978       daemon_functions in
4979   let proc_nrs =
4980     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4981   let rec loop = function
4982     | [] -> ()
4983     | [_] -> ()
4984     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4985         loop rest
4986     | (name1,nr1) :: (name2,nr2) :: _ ->
4987         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4988           name1 name2 nr1 nr2
4989   in
4990   loop proc_nrs;
4991
4992   (* Check tests. *)
4993   List.iter (
4994     function
4995       (* Ignore functions that have no tests.  We generate a
4996        * warning when the user does 'make check' instead.
4997        *)
4998     | name, _, _, _, [], _, _ -> ()
4999     | name, _, _, _, tests, _, _ ->
5000         let funcs =
5001           List.map (
5002             fun (_, _, test) ->
5003               match seq_of_test test with
5004               | [] ->
5005                   failwithf "%s has a test containing an empty sequence" name
5006               | cmds -> List.map List.hd cmds
5007           ) tests in
5008         let funcs = List.flatten funcs in
5009
5010         let tested = List.mem name funcs in
5011
5012         if not tested then
5013           failwithf "function %s has tests but does not test itself" name
5014   ) all_functions
5015
5016 (* 'pr' prints to the current output file. *)
5017 let chan = ref Pervasives.stdout
5018 let lines = ref 0
5019 let pr fs =
5020   ksprintf
5021     (fun str ->
5022        let i = count_chars '\n' str in
5023        lines := !lines + i;
5024        output_string !chan str
5025     ) fs
5026
5027 let copyright_years =
5028   let this_year = 1900 + (localtime (time ())).tm_year in
5029   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5030
5031 (* Generate a header block in a number of standard styles. *)
5032 type comment_style =
5033     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5034 type license = GPLv2plus | LGPLv2plus
5035
5036 let generate_header ?(extra_inputs = []) comment license =
5037   let inputs = "src/generator.ml" :: extra_inputs in
5038   let c = match comment with
5039     | CStyle ->         pr "/* "; " *"
5040     | CPlusPlusStyle -> pr "// "; "//"
5041     | HashStyle ->      pr "# ";  "#"
5042     | OCamlStyle ->     pr "(* "; " *"
5043     | HaskellStyle ->   pr "{- "; "  " in
5044   pr "libguestfs generated file\n";
5045   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5046   List.iter (pr "%s   %s\n" c) inputs;
5047   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5048   pr "%s\n" c;
5049   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5050   pr "%s\n" c;
5051   (match license with
5052    | GPLv2plus ->
5053        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5054        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5055        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5056        pr "%s (at your option) any later version.\n" c;
5057        pr "%s\n" c;
5058        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5059        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5060        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5061        pr "%s GNU General Public License for more details.\n" c;
5062        pr "%s\n" c;
5063        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5064        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5065        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5066
5067    | LGPLv2plus ->
5068        pr "%s This library is free software; you can redistribute it and/or\n" c;
5069        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5070        pr "%s License as published by the Free Software Foundation; either\n" c;
5071        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5072        pr "%s\n" c;
5073        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5074        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5075        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5076        pr "%s Lesser General Public License for more details.\n" c;
5077        pr "%s\n" c;
5078        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5079        pr "%s License along with this library; if not, write to the Free Software\n" c;
5080        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5081   );
5082   (match comment with
5083    | CStyle -> pr " */\n"
5084    | CPlusPlusStyle
5085    | HashStyle -> ()
5086    | OCamlStyle -> pr " *)\n"
5087    | HaskellStyle -> pr "-}\n"
5088   );
5089   pr "\n"
5090
5091 (* Start of main code generation functions below this line. *)
5092
5093 (* Generate the pod documentation for the C API. *)
5094 let rec generate_actions_pod () =
5095   List.iter (
5096     fun (shortname, style, _, flags, _, _, longdesc) ->
5097       if not (List.mem NotInDocs flags) then (
5098         let name = "guestfs_" ^ shortname in
5099         pr "=head2 %s\n\n" name;
5100         pr " ";
5101         generate_prototype ~extern:false ~handle:"handle" name style;
5102         pr "\n\n";
5103         pr "%s\n\n" longdesc;
5104         (match fst style with
5105          | RErr ->
5106              pr "This function returns 0 on success or -1 on error.\n\n"
5107          | RInt _ ->
5108              pr "On error this function returns -1.\n\n"
5109          | RInt64 _ ->
5110              pr "On error this function returns -1.\n\n"
5111          | RBool _ ->
5112              pr "This function returns a C truth value on success or -1 on error.\n\n"
5113          | RConstString _ ->
5114              pr "This function returns a string, or NULL on error.
5115 The string is owned by the guest handle and must I<not> be freed.\n\n"
5116          | RConstOptString _ ->
5117              pr "This function returns a string which may be NULL.
5118 There is way to return an error from this function.
5119 The string is owned by the guest handle and must I<not> be freed.\n\n"
5120          | RString _ ->
5121              pr "This function returns a string, or NULL on error.
5122 I<The caller must free the returned string after use>.\n\n"
5123          | RStringList _ ->
5124              pr "This function returns a NULL-terminated array of strings
5125 (like L<environ(3)>), or NULL if there was an error.
5126 I<The caller must free the strings and the array after use>.\n\n"
5127          | RStruct (_, typ) ->
5128              pr "This function returns a C<struct guestfs_%s *>,
5129 or NULL if there was an error.
5130 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5131          | RStructList (_, typ) ->
5132              pr "This function returns a C<struct guestfs_%s_list *>
5133 (see E<lt>guestfs-structs.hE<gt>),
5134 or NULL if there was an error.
5135 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5136          | RHashtable _ ->
5137              pr "This function returns a NULL-terminated array of
5138 strings, or NULL if there was an error.
5139 The array of strings will always have length C<2n+1>, where
5140 C<n> keys and values alternate, followed by the trailing NULL entry.
5141 I<The caller must free the strings and the array after use>.\n\n"
5142          | RBufferOut _ ->
5143              pr "This function returns a buffer, or NULL on error.
5144 The size of the returned buffer is written to C<*size_r>.
5145 I<The caller must free the returned buffer after use>.\n\n"
5146         );
5147         if List.mem ProtocolLimitWarning flags then
5148           pr "%s\n\n" protocol_limit_warning;
5149         if List.mem DangerWillRobinson flags then
5150           pr "%s\n\n" danger_will_robinson;
5151         match deprecation_notice flags with
5152         | None -> ()
5153         | Some txt -> pr "%s\n\n" txt
5154       )
5155   ) all_functions_sorted
5156
5157 and generate_structs_pod () =
5158   (* Structs documentation. *)
5159   List.iter (
5160     fun (typ, cols) ->
5161       pr "=head2 guestfs_%s\n" typ;
5162       pr "\n";
5163       pr " struct guestfs_%s {\n" typ;
5164       List.iter (
5165         function
5166         | name, FChar -> pr "   char %s;\n" name
5167         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5168         | name, FInt32 -> pr "   int32_t %s;\n" name
5169         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5170         | name, FInt64 -> pr "   int64_t %s;\n" name
5171         | name, FString -> pr "   char *%s;\n" name
5172         | name, FBuffer ->
5173             pr "   /* The next two fields describe a byte array. */\n";
5174             pr "   uint32_t %s_len;\n" name;
5175             pr "   char *%s;\n" name
5176         | name, FUUID ->
5177             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5178             pr "   char %s[32];\n" name
5179         | name, FOptPercent ->
5180             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5181             pr "   float %s;\n" name
5182       ) cols;
5183       pr " };\n";
5184       pr " \n";
5185       pr " struct guestfs_%s_list {\n" typ;
5186       pr "   uint32_t len; /* Number of elements in list. */\n";
5187       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5188       pr " };\n";
5189       pr " \n";
5190       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5191       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5192         typ typ;
5193       pr "\n"
5194   ) structs
5195
5196 and generate_availability_pod () =
5197   (* Availability documentation. *)
5198   pr "=over 4\n";
5199   pr "\n";
5200   List.iter (
5201     fun (group, functions) ->
5202       pr "=item B<%s>\n" group;
5203       pr "\n";
5204       pr "The following functions:\n";
5205       List.iter (pr "L</guestfs_%s>\n") functions;
5206       pr "\n"
5207   ) optgroups;
5208   pr "=back\n";
5209   pr "\n"
5210
5211 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5212  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5213  *
5214  * We have to use an underscore instead of a dash because otherwise
5215  * rpcgen generates incorrect code.
5216  *
5217  * This header is NOT exported to clients, but see also generate_structs_h.
5218  *)
5219 and generate_xdr () =
5220   generate_header CStyle LGPLv2plus;
5221
5222   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5223   pr "typedef string str<>;\n";
5224   pr "\n";
5225
5226   (* Internal structures. *)
5227   List.iter (
5228     function
5229     | typ, cols ->
5230         pr "struct guestfs_int_%s {\n" typ;
5231         List.iter (function
5232                    | name, FChar -> pr "  char %s;\n" name
5233                    | name, FString -> pr "  string %s<>;\n" name
5234                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5235                    | name, FUUID -> pr "  opaque %s[32];\n" name
5236                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5237                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5238                    | name, FOptPercent -> pr "  float %s;\n" name
5239                   ) cols;
5240         pr "};\n";
5241         pr "\n";
5242         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5243         pr "\n";
5244   ) structs;
5245
5246   List.iter (
5247     fun (shortname, style, _, _, _, _, _) ->
5248       let name = "guestfs_" ^ shortname in
5249
5250       (match snd style with
5251        | [] -> ()
5252        | args ->
5253            pr "struct %s_args {\n" name;
5254            List.iter (
5255              function
5256              | Pathname n | Device n | Dev_or_Path n | String n ->
5257                  pr "  string %s<>;\n" n
5258              | OptString n -> pr "  str *%s;\n" n
5259              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5260              | Bool n -> pr "  bool %s;\n" n
5261              | Int n -> pr "  int %s;\n" n
5262              | Int64 n -> pr "  hyper %s;\n" n
5263              | FileIn _ | FileOut _ -> ()
5264            ) args;
5265            pr "};\n\n"
5266       );
5267       (match fst style with
5268        | RErr -> ()
5269        | RInt n ->
5270            pr "struct %s_ret {\n" name;
5271            pr "  int %s;\n" n;
5272            pr "};\n\n"
5273        | RInt64 n ->
5274            pr "struct %s_ret {\n" name;
5275            pr "  hyper %s;\n" n;
5276            pr "};\n\n"
5277        | RBool n ->
5278            pr "struct %s_ret {\n" name;
5279            pr "  bool %s;\n" n;
5280            pr "};\n\n"
5281        | RConstString _ | RConstOptString _ ->
5282            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5283        | RString n ->
5284            pr "struct %s_ret {\n" name;
5285            pr "  string %s<>;\n" n;
5286            pr "};\n\n"
5287        | RStringList n ->
5288            pr "struct %s_ret {\n" name;
5289            pr "  str %s<>;\n" n;
5290            pr "};\n\n"
5291        | RStruct (n, typ) ->
5292            pr "struct %s_ret {\n" name;
5293            pr "  guestfs_int_%s %s;\n" typ n;
5294            pr "};\n\n"
5295        | RStructList (n, typ) ->
5296            pr "struct %s_ret {\n" name;
5297            pr "  guestfs_int_%s_list %s;\n" typ n;
5298            pr "};\n\n"
5299        | RHashtable n ->
5300            pr "struct %s_ret {\n" name;
5301            pr "  str %s<>;\n" n;
5302            pr "};\n\n"
5303        | RBufferOut n ->
5304            pr "struct %s_ret {\n" name;
5305            pr "  opaque %s<>;\n" n;
5306            pr "};\n\n"
5307       );
5308   ) daemon_functions;
5309
5310   (* Table of procedure numbers. *)
5311   pr "enum guestfs_procedure {\n";
5312   List.iter (
5313     fun (shortname, _, proc_nr, _, _, _, _) ->
5314       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5315   ) daemon_functions;
5316   pr "  GUESTFS_PROC_NR_PROCS\n";
5317   pr "};\n";
5318   pr "\n";
5319
5320   (* Having to choose a maximum message size is annoying for several
5321    * reasons (it limits what we can do in the API), but it (a) makes
5322    * the protocol a lot simpler, and (b) provides a bound on the size
5323    * of the daemon which operates in limited memory space.
5324    *)
5325   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5326   pr "\n";
5327
5328   (* Message header, etc. *)
5329   pr "\
5330 /* The communication protocol is now documented in the guestfs(3)
5331  * manpage.
5332  */
5333
5334 const GUESTFS_PROGRAM = 0x2000F5F5;
5335 const GUESTFS_PROTOCOL_VERSION = 1;
5336
5337 /* These constants must be larger than any possible message length. */
5338 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5339 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5340
5341 enum guestfs_message_direction {
5342   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5343   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5344 };
5345
5346 enum guestfs_message_status {
5347   GUESTFS_STATUS_OK = 0,
5348   GUESTFS_STATUS_ERROR = 1
5349 };
5350
5351 const GUESTFS_ERROR_LEN = 256;
5352
5353 struct guestfs_message_error {
5354   string error_message<GUESTFS_ERROR_LEN>;
5355 };
5356
5357 struct guestfs_message_header {
5358   unsigned prog;                     /* GUESTFS_PROGRAM */
5359   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5360   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5361   guestfs_message_direction direction;
5362   unsigned serial;                   /* message serial number */
5363   guestfs_message_status status;
5364 };
5365
5366 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5367
5368 struct guestfs_chunk {
5369   int cancel;                        /* if non-zero, transfer is cancelled */
5370   /* data size is 0 bytes if the transfer has finished successfully */
5371   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5372 };
5373 "
5374
5375 (* Generate the guestfs-structs.h file. *)
5376 and generate_structs_h () =
5377   generate_header CStyle LGPLv2plus;
5378
5379   (* This is a public exported header file containing various
5380    * structures.  The structures are carefully written to have
5381    * exactly the same in-memory format as the XDR structures that
5382    * we use on the wire to the daemon.  The reason for creating
5383    * copies of these structures here is just so we don't have to
5384    * export the whole of guestfs_protocol.h (which includes much
5385    * unrelated and XDR-dependent stuff that we don't want to be
5386    * public, or required by clients).
5387    *
5388    * To reiterate, we will pass these structures to and from the
5389    * client with a simple assignment or memcpy, so the format
5390    * must be identical to what rpcgen / the RFC defines.
5391    *)
5392
5393   (* Public structures. *)
5394   List.iter (
5395     fun (typ, cols) ->
5396       pr "struct guestfs_%s {\n" typ;
5397       List.iter (
5398         function
5399         | name, FChar -> pr "  char %s;\n" name
5400         | name, FString -> pr "  char *%s;\n" name
5401         | name, FBuffer ->
5402             pr "  uint32_t %s_len;\n" name;
5403             pr "  char *%s;\n" name
5404         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5405         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5406         | name, FInt32 -> pr "  int32_t %s;\n" name
5407         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5408         | name, FInt64 -> pr "  int64_t %s;\n" name
5409         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5410       ) cols;
5411       pr "};\n";
5412       pr "\n";
5413       pr "struct guestfs_%s_list {\n" typ;
5414       pr "  uint32_t len;\n";
5415       pr "  struct guestfs_%s *val;\n" typ;
5416       pr "};\n";
5417       pr "\n";
5418       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5419       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5420       pr "\n"
5421   ) structs
5422
5423 (* Generate the guestfs-actions.h file. *)
5424 and generate_actions_h () =
5425   generate_header CStyle LGPLv2plus;
5426   List.iter (
5427     fun (shortname, style, _, _, _, _, _) ->
5428       let name = "guestfs_" ^ shortname in
5429       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5430         name style
5431   ) all_functions
5432
5433 (* Generate the guestfs-internal-actions.h file. *)
5434 and generate_internal_actions_h () =
5435   generate_header CStyle LGPLv2plus;
5436   List.iter (
5437     fun (shortname, style, _, _, _, _, _) ->
5438       let name = "guestfs__" ^ shortname in
5439       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5440         name style
5441   ) non_daemon_functions
5442
5443 (* Generate the client-side dispatch stubs. *)
5444 and generate_client_actions () =
5445   generate_header CStyle LGPLv2plus;
5446
5447   pr "\
5448 #include <stdio.h>
5449 #include <stdlib.h>
5450 #include <stdint.h>
5451 #include <string.h>
5452 #include <inttypes.h>
5453
5454 #include \"guestfs.h\"
5455 #include \"guestfs-internal.h\"
5456 #include \"guestfs-internal-actions.h\"
5457 #include \"guestfs_protocol.h\"
5458
5459 #define error guestfs_error
5460 //#define perrorf guestfs_perrorf
5461 #define safe_malloc guestfs_safe_malloc
5462 #define safe_realloc guestfs_safe_realloc
5463 //#define safe_strdup guestfs_safe_strdup
5464 #define safe_memdup guestfs_safe_memdup
5465
5466 /* Check the return message from a call for validity. */
5467 static int
5468 check_reply_header (guestfs_h *g,
5469                     const struct guestfs_message_header *hdr,
5470                     unsigned int proc_nr, unsigned int serial)
5471 {
5472   if (hdr->prog != GUESTFS_PROGRAM) {
5473     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5474     return -1;
5475   }
5476   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5477     error (g, \"wrong protocol version (%%d/%%d)\",
5478            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5479     return -1;
5480   }
5481   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5482     error (g, \"unexpected message direction (%%d/%%d)\",
5483            hdr->direction, GUESTFS_DIRECTION_REPLY);
5484     return -1;
5485   }
5486   if (hdr->proc != proc_nr) {
5487     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5488     return -1;
5489   }
5490   if (hdr->serial != serial) {
5491     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5492     return -1;
5493   }
5494
5495   return 0;
5496 }
5497
5498 /* Check we are in the right state to run a high-level action. */
5499 static int
5500 check_state (guestfs_h *g, const char *caller)
5501 {
5502   if (!guestfs__is_ready (g)) {
5503     if (guestfs__is_config (g) || guestfs__is_launching (g))
5504       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5505         caller);
5506     else
5507       error (g, \"%%s called from the wrong state, %%d != READY\",
5508         caller, guestfs__get_state (g));
5509     return -1;
5510   }
5511   return 0;
5512 }
5513
5514 ";
5515
5516   (* Generate code to generate guestfish call traces. *)
5517   let trace_call shortname style =
5518     pr "  if (guestfs__get_trace (g)) {\n";
5519
5520     let needs_i =
5521       List.exists (function
5522                    | StringList _ | DeviceList _ -> true
5523                    | _ -> false) (snd style) in
5524     if needs_i then (
5525       pr "    int i;\n";
5526       pr "\n"
5527     );
5528
5529     pr "    printf (\"%s\");\n" shortname;
5530     List.iter (
5531       function
5532       | String n                        (* strings *)
5533       | Device n
5534       | Pathname n
5535       | Dev_or_Path n
5536       | FileIn n
5537       | FileOut n ->
5538           (* guestfish doesn't support string escaping, so neither do we *)
5539           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5540       | OptString n ->                  (* string option *)
5541           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5542           pr "    else printf (\" null\");\n"
5543       | StringList n
5544       | DeviceList n ->                 (* string list *)
5545           pr "    putchar (' ');\n";
5546           pr "    putchar ('\"');\n";
5547           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5548           pr "      if (i > 0) putchar (' ');\n";
5549           pr "      fputs (%s[i], stdout);\n" n;
5550           pr "    }\n";
5551           pr "    putchar ('\"');\n";
5552       | Bool n ->                       (* boolean *)
5553           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5554       | Int n ->                        (* int *)
5555           pr "    printf (\" %%d\", %s);\n" n
5556       | Int64 n ->
5557           pr "    printf (\" %%\" PRIi64, %s);\n" n
5558     ) (snd style);
5559     pr "    putchar ('\\n');\n";
5560     pr "  }\n";
5561     pr "\n";
5562   in
5563
5564   (* For non-daemon functions, generate a wrapper around each function. *)
5565   List.iter (
5566     fun (shortname, style, _, _, _, _, _) ->
5567       let name = "guestfs_" ^ shortname in
5568
5569       generate_prototype ~extern:false ~semicolon:false ~newline:true
5570         ~handle:"g" name style;
5571       pr "{\n";
5572       trace_call shortname style;
5573       pr "  return guestfs__%s " shortname;
5574       generate_c_call_args ~handle:"g" style;
5575       pr ";\n";
5576       pr "}\n";
5577       pr "\n"
5578   ) non_daemon_functions;
5579
5580   (* Client-side stubs for each function. *)
5581   List.iter (
5582     fun (shortname, style, _, _, _, _, _) ->
5583       let name = "guestfs_" ^ shortname in
5584
5585       (* Generate the action stub. *)
5586       generate_prototype ~extern:false ~semicolon:false ~newline:true
5587         ~handle:"g" name style;
5588
5589       let error_code =
5590         match fst style with
5591         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5592         | RConstString _ | RConstOptString _ ->
5593             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5594         | RString _ | RStringList _
5595         | RStruct _ | RStructList _
5596         | RHashtable _ | RBufferOut _ ->
5597             "NULL" in
5598
5599       pr "{\n";
5600
5601       (match snd style with
5602        | [] -> ()
5603        | _ -> pr "  struct %s_args args;\n" name
5604       );
5605
5606       pr "  guestfs_message_header hdr;\n";
5607       pr "  guestfs_message_error err;\n";
5608       let has_ret =
5609         match fst style with
5610         | RErr -> false
5611         | RConstString _ | RConstOptString _ ->
5612             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5613         | RInt _ | RInt64 _
5614         | RBool _ | RString _ | RStringList _
5615         | RStruct _ | RStructList _
5616         | RHashtable _ | RBufferOut _ ->
5617             pr "  struct %s_ret ret;\n" name;
5618             true in
5619
5620       pr "  int serial;\n";
5621       pr "  int r;\n";
5622       pr "\n";
5623       trace_call shortname style;
5624       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5625       pr "  guestfs___set_busy (g);\n";
5626       pr "\n";
5627
5628       (* Send the main header and arguments. *)
5629       (match snd style with
5630        | [] ->
5631            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5632              (String.uppercase shortname)
5633        | args ->
5634            List.iter (
5635              function
5636              | Pathname n | Device n | Dev_or_Path n | String n ->
5637                  pr "  args.%s = (char *) %s;\n" n n
5638              | OptString n ->
5639                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5640              | StringList n | DeviceList n ->
5641                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5642                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5643              | Bool n ->
5644                  pr "  args.%s = %s;\n" n n
5645              | Int n ->
5646                  pr "  args.%s = %s;\n" n n
5647              | Int64 n ->
5648                  pr "  args.%s = %s;\n" n n
5649              | FileIn _ | FileOut _ -> ()
5650            ) args;
5651            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5652              (String.uppercase shortname);
5653            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5654              name;
5655       );
5656       pr "  if (serial == -1) {\n";
5657       pr "    guestfs___end_busy (g);\n";
5658       pr "    return %s;\n" error_code;
5659       pr "  }\n";
5660       pr "\n";
5661
5662       (* Send any additional files (FileIn) requested. *)
5663       let need_read_reply_label = ref false in
5664       List.iter (
5665         function
5666         | FileIn n ->
5667             pr "  r = guestfs___send_file (g, %s);\n" n;
5668             pr "  if (r == -1) {\n";
5669             pr "    guestfs___end_busy (g);\n";
5670             pr "    return %s;\n" error_code;
5671             pr "  }\n";
5672             pr "  if (r == -2) /* daemon cancelled */\n";
5673             pr "    goto read_reply;\n";
5674             need_read_reply_label := true;
5675             pr "\n";
5676         | _ -> ()
5677       ) (snd style);
5678
5679       (* Wait for the reply from the remote end. *)
5680       if !need_read_reply_label then pr " read_reply:\n";
5681       pr "  memset (&hdr, 0, sizeof hdr);\n";
5682       pr "  memset (&err, 0, sizeof err);\n";
5683       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5684       pr "\n";
5685       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5686       if not has_ret then
5687         pr "NULL, NULL"
5688       else
5689         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5690       pr ");\n";
5691
5692       pr "  if (r == -1) {\n";
5693       pr "    guestfs___end_busy (g);\n";
5694       pr "    return %s;\n" error_code;
5695       pr "  }\n";
5696       pr "\n";
5697
5698       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5699         (String.uppercase shortname);
5700       pr "    guestfs___end_busy (g);\n";
5701       pr "    return %s;\n" error_code;
5702       pr "  }\n";
5703       pr "\n";
5704
5705       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5706       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5707       pr "    free (err.error_message);\n";
5708       pr "    guestfs___end_busy (g);\n";
5709       pr "    return %s;\n" error_code;
5710       pr "  }\n";
5711       pr "\n";
5712
5713       (* Expecting to receive further files (FileOut)? *)
5714       List.iter (
5715         function
5716         | FileOut n ->
5717             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5718             pr "    guestfs___end_busy (g);\n";
5719             pr "    return %s;\n" error_code;
5720             pr "  }\n";
5721             pr "\n";
5722         | _ -> ()
5723       ) (snd style);
5724
5725       pr "  guestfs___end_busy (g);\n";
5726
5727       (match fst style with
5728        | RErr -> pr "  return 0;\n"
5729        | RInt n | RInt64 n | RBool n ->
5730            pr "  return ret.%s;\n" n
5731        | RConstString _ | RConstOptString _ ->
5732            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5733        | RString n ->
5734            pr "  return ret.%s; /* caller will free */\n" n
5735        | RStringList n | RHashtable n ->
5736            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5737            pr "  ret.%s.%s_val =\n" n n;
5738            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5739            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5740              n n;
5741            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5742            pr "  return ret.%s.%s_val;\n" n n
5743        | RStruct (n, _) ->
5744            pr "  /* caller will free this */\n";
5745            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5746        | RStructList (n, _) ->
5747            pr "  /* caller will free this */\n";
5748            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5749        | RBufferOut n ->
5750            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5751            pr "   * _val might be NULL here.  To make the API saner for\n";
5752            pr "   * callers, we turn this case into a unique pointer (using\n";
5753            pr "   * malloc(1)).\n";
5754            pr "   */\n";
5755            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5756            pr "    *size_r = ret.%s.%s_len;\n" n n;
5757            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5758            pr "  } else {\n";
5759            pr "    free (ret.%s.%s_val);\n" n n;
5760            pr "    char *p = safe_malloc (g, 1);\n";
5761            pr "    *size_r = ret.%s.%s_len;\n" n n;
5762            pr "    return p;\n";
5763            pr "  }\n";
5764       );
5765
5766       pr "}\n\n"
5767   ) daemon_functions;
5768
5769   (* Functions to free structures. *)
5770   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5771   pr " * structure format is identical to the XDR format.  See note in\n";
5772   pr " * generator.ml.\n";
5773   pr " */\n";
5774   pr "\n";
5775
5776   List.iter (
5777     fun (typ, _) ->
5778       pr "void\n";
5779       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5780       pr "{\n";
5781       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5782       pr "  free (x);\n";
5783       pr "}\n";
5784       pr "\n";
5785
5786       pr "void\n";
5787       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5788       pr "{\n";
5789       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5790       pr "  free (x);\n";
5791       pr "}\n";
5792       pr "\n";
5793
5794   ) structs;
5795
5796 (* Generate daemon/actions.h. *)
5797 and generate_daemon_actions_h () =
5798   generate_header CStyle GPLv2plus;
5799
5800   pr "#include \"../src/guestfs_protocol.h\"\n";
5801   pr "\n";
5802
5803   List.iter (
5804     fun (name, style, _, _, _, _, _) ->
5805       generate_prototype
5806         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5807         name style;
5808   ) daemon_functions
5809
5810 (* Generate the linker script which controls the visibility of
5811  * symbols in the public ABI and ensures no other symbols get
5812  * exported accidentally.
5813  *)
5814 and generate_linker_script () =
5815   generate_header HashStyle GPLv2plus;
5816
5817   let globals = [
5818     "guestfs_create";
5819     "guestfs_close";
5820     "guestfs_get_error_handler";
5821     "guestfs_get_out_of_memory_handler";
5822     "guestfs_last_error";
5823     "guestfs_set_error_handler";
5824     "guestfs_set_launch_done_callback";
5825     "guestfs_set_log_message_callback";
5826     "guestfs_set_out_of_memory_handler";
5827     "guestfs_set_subprocess_quit_callback";
5828
5829     (* Unofficial parts of the API: the bindings code use these
5830      * functions, so it is useful to export them.
5831      *)
5832     "guestfs_safe_calloc";
5833     "guestfs_safe_malloc";
5834   ] in
5835   let functions =
5836     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5837       all_functions in
5838   let structs =
5839     List.concat (
5840       List.map (fun (typ, _) ->
5841                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5842         structs
5843     ) in
5844   let globals = List.sort compare (globals @ functions @ structs) in
5845
5846   pr "{\n";
5847   pr "    global:\n";
5848   List.iter (pr "        %s;\n") globals;
5849   pr "\n";
5850
5851   pr "    local:\n";
5852   pr "        *;\n";
5853   pr "};\n"
5854
5855 (* Generate the server-side stubs. *)
5856 and generate_daemon_actions () =
5857   generate_header CStyle GPLv2plus;
5858
5859   pr "#include <config.h>\n";
5860   pr "\n";
5861   pr "#include <stdio.h>\n";
5862   pr "#include <stdlib.h>\n";
5863   pr "#include <string.h>\n";
5864   pr "#include <inttypes.h>\n";
5865   pr "#include <rpc/types.h>\n";
5866   pr "#include <rpc/xdr.h>\n";
5867   pr "\n";
5868   pr "#include \"daemon.h\"\n";
5869   pr "#include \"c-ctype.h\"\n";
5870   pr "#include \"../src/guestfs_protocol.h\"\n";
5871   pr "#include \"actions.h\"\n";
5872   pr "\n";
5873
5874   List.iter (
5875     fun (name, style, _, _, _, _, _) ->
5876       (* Generate server-side stubs. *)
5877       pr "static void %s_stub (XDR *xdr_in)\n" name;
5878       pr "{\n";
5879       let error_code =
5880         match fst style with
5881         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5882         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5883         | RBool _ -> pr "  int r;\n"; "-1"
5884         | RConstString _ | RConstOptString _ ->
5885             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5886         | RString _ -> pr "  char *r;\n"; "NULL"
5887         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5888         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5889         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5890         | RBufferOut _ ->
5891             pr "  size_t size = 1;\n";
5892             pr "  char *r;\n";
5893             "NULL" in
5894
5895       (match snd style with
5896        | [] -> ()
5897        | args ->
5898            pr "  struct guestfs_%s_args args;\n" name;
5899            List.iter (
5900              function
5901              | Device n | Dev_or_Path n
5902              | Pathname n
5903              | String n -> ()
5904              | OptString n -> pr "  char *%s;\n" n
5905              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5906              | Bool n -> pr "  int %s;\n" n
5907              | Int n -> pr "  int %s;\n" n
5908              | Int64 n -> pr "  int64_t %s;\n" n
5909              | FileIn _ | FileOut _ -> ()
5910            ) args
5911       );
5912       pr "\n";
5913
5914       (match snd style with
5915        | [] -> ()
5916        | args ->
5917            pr "  memset (&args, 0, sizeof args);\n";
5918            pr "\n";
5919            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5920            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5921            pr "    return;\n";
5922            pr "  }\n";
5923            let pr_args n =
5924              pr "  char *%s = args.%s;\n" n n
5925            in
5926            let pr_list_handling_code n =
5927              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5928              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5929              pr "  if (%s == NULL) {\n" n;
5930              pr "    reply_with_perror (\"realloc\");\n";
5931              pr "    goto done;\n";
5932              pr "  }\n";
5933              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5934              pr "  args.%s.%s_val = %s;\n" n n n;
5935            in
5936            List.iter (
5937              function
5938              | Pathname n ->
5939                  pr_args n;
5940                  pr "  ABS_PATH (%s, goto done);\n" n;
5941              | Device n ->
5942                  pr_args n;
5943                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5944              | Dev_or_Path n ->
5945                  pr_args n;
5946                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5947              | String n -> pr_args n
5948              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5949              | StringList n ->
5950                  pr_list_handling_code n;
5951              | DeviceList n ->
5952                  pr_list_handling_code n;
5953                  pr "  /* Ensure that each is a device,\n";
5954                  pr "   * and perform device name translation. */\n";
5955                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5956                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5957                  pr "  }\n";
5958              | Bool n -> pr "  %s = args.%s;\n" n n
5959              | Int n -> pr "  %s = args.%s;\n" n n
5960              | Int64 n -> pr "  %s = args.%s;\n" n n
5961              | FileIn _ | FileOut _ -> ()
5962            ) args;
5963            pr "\n"
5964       );
5965
5966
5967       (* this is used at least for do_equal *)
5968       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5969         (* Emit NEED_ROOT just once, even when there are two or
5970            more Pathname args *)
5971         pr "  NEED_ROOT (goto done);\n";
5972       );
5973
5974       (* Don't want to call the impl with any FileIn or FileOut
5975        * parameters, since these go "outside" the RPC protocol.
5976        *)
5977       let args' =
5978         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5979           (snd style) in
5980       pr "  r = do_%s " name;
5981       generate_c_call_args (fst style, args');
5982       pr ";\n";
5983
5984       (match fst style with
5985        | RErr | RInt _ | RInt64 _ | RBool _
5986        | RConstString _ | RConstOptString _
5987        | RString _ | RStringList _ | RHashtable _
5988        | RStruct (_, _) | RStructList (_, _) ->
5989            pr "  if (r == %s)\n" error_code;
5990            pr "    /* do_%s has already called reply_with_error */\n" name;
5991            pr "    goto done;\n";
5992            pr "\n"
5993        | RBufferOut _ ->
5994            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5995            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5996            pr "   */\n";
5997            pr "  if (size == 1 && r == %s)\n" error_code;
5998            pr "    /* do_%s has already called reply_with_error */\n" name;
5999            pr "    goto done;\n";
6000            pr "\n"
6001       );
6002
6003       (* If there are any FileOut parameters, then the impl must
6004        * send its own reply.
6005        *)
6006       let no_reply =
6007         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6008       if no_reply then
6009         pr "  /* do_%s has already sent a reply */\n" name
6010       else (
6011         match fst style with
6012         | RErr -> pr "  reply (NULL, NULL);\n"
6013         | RInt n | RInt64 n | RBool n ->
6014             pr "  struct guestfs_%s_ret ret;\n" name;
6015             pr "  ret.%s = r;\n" n;
6016             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6017               name
6018         | RConstString _ | RConstOptString _ ->
6019             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6020         | RString n ->
6021             pr "  struct guestfs_%s_ret ret;\n" name;
6022             pr "  ret.%s = r;\n" n;
6023             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6024               name;
6025             pr "  free (r);\n"
6026         | RStringList n | RHashtable n ->
6027             pr "  struct guestfs_%s_ret ret;\n" name;
6028             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6029             pr "  ret.%s.%s_val = r;\n" n n;
6030             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6031               name;
6032             pr "  free_strings (r);\n"
6033         | RStruct (n, _) ->
6034             pr "  struct guestfs_%s_ret ret;\n" name;
6035             pr "  ret.%s = *r;\n" n;
6036             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6037               name;
6038             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6039               name
6040         | RStructList (n, _) ->
6041             pr "  struct guestfs_%s_ret ret;\n" name;
6042             pr "  ret.%s = *r;\n" n;
6043             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6044               name;
6045             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6046               name
6047         | RBufferOut n ->
6048             pr "  struct guestfs_%s_ret ret;\n" name;
6049             pr "  ret.%s.%s_val = r;\n" n n;
6050             pr "  ret.%s.%s_len = size;\n" n n;
6051             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6052               name;
6053             pr "  free (r);\n"
6054       );
6055
6056       (* Free the args. *)
6057       (match snd style with
6058        | [] ->
6059            pr "done: ;\n";
6060        | _ ->
6061            pr "done:\n";
6062            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6063              name
6064       );
6065
6066       pr "}\n\n";
6067   ) daemon_functions;
6068
6069   (* Dispatch function. *)
6070   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6071   pr "{\n";
6072   pr "  switch (proc_nr) {\n";
6073
6074   List.iter (
6075     fun (name, style, _, _, _, _, _) ->
6076       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6077       pr "      %s_stub (xdr_in);\n" name;
6078       pr "      break;\n"
6079   ) daemon_functions;
6080
6081   pr "    default:\n";
6082   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";
6083   pr "  }\n";
6084   pr "}\n";
6085   pr "\n";
6086
6087   (* LVM columns and tokenization functions. *)
6088   (* XXX This generates crap code.  We should rethink how we
6089    * do this parsing.
6090    *)
6091   List.iter (
6092     function
6093     | typ, cols ->
6094         pr "static const char *lvm_%s_cols = \"%s\";\n"
6095           typ (String.concat "," (List.map fst cols));
6096         pr "\n";
6097
6098         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6099         pr "{\n";
6100         pr "  char *tok, *p, *next;\n";
6101         pr "  int i, j;\n";
6102         pr "\n";
6103         (*
6104           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6105           pr "\n";
6106         *)
6107         pr "  if (!str) {\n";
6108         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6109         pr "    return -1;\n";
6110         pr "  }\n";
6111         pr "  if (!*str || c_isspace (*str)) {\n";
6112         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6113         pr "    return -1;\n";
6114         pr "  }\n";
6115         pr "  tok = str;\n";
6116         List.iter (
6117           fun (name, coltype) ->
6118             pr "  if (!tok) {\n";
6119             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6120             pr "    return -1;\n";
6121             pr "  }\n";
6122             pr "  p = strchrnul (tok, ',');\n";
6123             pr "  if (*p) next = p+1; else next = NULL;\n";
6124             pr "  *p = '\\0';\n";
6125             (match coltype with
6126              | FString ->
6127                  pr "  r->%s = strdup (tok);\n" name;
6128                  pr "  if (r->%s == NULL) {\n" name;
6129                  pr "    perror (\"strdup\");\n";
6130                  pr "    return -1;\n";
6131                  pr "  }\n"
6132              | FUUID ->
6133                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6134                  pr "    if (tok[j] == '\\0') {\n";
6135                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6136                  pr "      return -1;\n";
6137                  pr "    } else if (tok[j] != '-')\n";
6138                  pr "      r->%s[i++] = tok[j];\n" name;
6139                  pr "  }\n";
6140              | FBytes ->
6141                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6142                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6143                  pr "    return -1;\n";
6144                  pr "  }\n";
6145              | FInt64 ->
6146                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6147                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6148                  pr "    return -1;\n";
6149                  pr "  }\n";
6150              | FOptPercent ->
6151                  pr "  if (tok[0] == '\\0')\n";
6152                  pr "    r->%s = -1;\n" name;
6153                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6154                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6155                  pr "    return -1;\n";
6156                  pr "  }\n";
6157              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6158                  assert false (* can never be an LVM column *)
6159             );
6160             pr "  tok = next;\n";
6161         ) cols;
6162
6163         pr "  if (tok != NULL) {\n";
6164         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6165         pr "    return -1;\n";
6166         pr "  }\n";
6167         pr "  return 0;\n";
6168         pr "}\n";
6169         pr "\n";
6170
6171         pr "guestfs_int_lvm_%s_list *\n" typ;
6172         pr "parse_command_line_%ss (void)\n" typ;
6173         pr "{\n";
6174         pr "  char *out, *err;\n";
6175         pr "  char *p, *pend;\n";
6176         pr "  int r, i;\n";
6177         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6178         pr "  void *newp;\n";
6179         pr "\n";
6180         pr "  ret = malloc (sizeof *ret);\n";
6181         pr "  if (!ret) {\n";
6182         pr "    reply_with_perror (\"malloc\");\n";
6183         pr "    return NULL;\n";
6184         pr "  }\n";
6185         pr "\n";
6186         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6187         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6188         pr "\n";
6189         pr "  r = command (&out, &err,\n";
6190         pr "           \"lvm\", \"%ss\",\n" typ;
6191         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6192         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6193         pr "  if (r == -1) {\n";
6194         pr "    reply_with_error (\"%%s\", err);\n";
6195         pr "    free (out);\n";
6196         pr "    free (err);\n";
6197         pr "    free (ret);\n";
6198         pr "    return NULL;\n";
6199         pr "  }\n";
6200         pr "\n";
6201         pr "  free (err);\n";
6202         pr "\n";
6203         pr "  /* Tokenize each line of the output. */\n";
6204         pr "  p = out;\n";
6205         pr "  i = 0;\n";
6206         pr "  while (p) {\n";
6207         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6208         pr "    if (pend) {\n";
6209         pr "      *pend = '\\0';\n";
6210         pr "      pend++;\n";
6211         pr "    }\n";
6212         pr "\n";
6213         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6214         pr "      p++;\n";
6215         pr "\n";
6216         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6217         pr "      p = pend;\n";
6218         pr "      continue;\n";
6219         pr "    }\n";
6220         pr "\n";
6221         pr "    /* Allocate some space to store this next entry. */\n";
6222         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6223         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6224         pr "    if (newp == NULL) {\n";
6225         pr "      reply_with_perror (\"realloc\");\n";
6226         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6227         pr "      free (ret);\n";
6228         pr "      free (out);\n";
6229         pr "      return NULL;\n";
6230         pr "    }\n";
6231         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6232         pr "\n";
6233         pr "    /* Tokenize the next entry. */\n";
6234         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6235         pr "    if (r == -1) {\n";
6236         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6237         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6238         pr "      free (ret);\n";
6239         pr "      free (out);\n";
6240         pr "      return NULL;\n";
6241         pr "    }\n";
6242         pr "\n";
6243         pr "    ++i;\n";
6244         pr "    p = pend;\n";
6245         pr "  }\n";
6246         pr "\n";
6247         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6248         pr "\n";
6249         pr "  free (out);\n";
6250         pr "  return ret;\n";
6251         pr "}\n"
6252
6253   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6254
6255 (* Generate a list of function names, for debugging in the daemon.. *)
6256 and generate_daemon_names () =
6257   generate_header CStyle GPLv2plus;
6258
6259   pr "#include <config.h>\n";
6260   pr "\n";
6261   pr "#include \"daemon.h\"\n";
6262   pr "\n";
6263
6264   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6265   pr "const char *function_names[] = {\n";
6266   List.iter (
6267     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6268   ) daemon_functions;
6269   pr "};\n";
6270
6271 (* Generate the optional groups for the daemon to implement
6272  * guestfs_available.
6273  *)
6274 and generate_daemon_optgroups_c () =
6275   generate_header CStyle GPLv2plus;
6276
6277   pr "#include <config.h>\n";
6278   pr "\n";
6279   pr "#include \"daemon.h\"\n";
6280   pr "#include \"optgroups.h\"\n";
6281   pr "\n";
6282
6283   pr "struct optgroup optgroups[] = {\n";
6284   List.iter (
6285     fun (group, _) ->
6286       pr "  { \"%s\", optgroup_%s_available },\n" group group
6287   ) optgroups;
6288   pr "  { NULL, NULL }\n";
6289   pr "};\n"
6290
6291 and generate_daemon_optgroups_h () =
6292   generate_header CStyle GPLv2plus;
6293
6294   List.iter (
6295     fun (group, _) ->
6296       pr "extern int optgroup_%s_available (void);\n" group
6297   ) optgroups
6298
6299 (* Generate the tests. *)
6300 and generate_tests () =
6301   generate_header CStyle GPLv2plus;
6302
6303   pr "\
6304 #include <stdio.h>
6305 #include <stdlib.h>
6306 #include <string.h>
6307 #include <unistd.h>
6308 #include <sys/types.h>
6309 #include <fcntl.h>
6310
6311 #include \"guestfs.h\"
6312 #include \"guestfs-internal.h\"
6313
6314 static guestfs_h *g;
6315 static int suppress_error = 0;
6316
6317 static void print_error (guestfs_h *g, void *data, const char *msg)
6318 {
6319   if (!suppress_error)
6320     fprintf (stderr, \"%%s\\n\", msg);
6321 }
6322
6323 /* FIXME: nearly identical code appears in fish.c */
6324 static void print_strings (char *const *argv)
6325 {
6326   int argc;
6327
6328   for (argc = 0; argv[argc] != NULL; ++argc)
6329     printf (\"\\t%%s\\n\", argv[argc]);
6330 }
6331
6332 /*
6333 static void print_table (char const *const *argv)
6334 {
6335   int i;
6336
6337   for (i = 0; argv[i] != NULL; i += 2)
6338     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6339 }
6340 */
6341
6342 ";
6343
6344   (* Generate a list of commands which are not tested anywhere. *)
6345   pr "static void no_test_warnings (void)\n";
6346   pr "{\n";
6347
6348   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6349   List.iter (
6350     fun (_, _, _, _, tests, _, _) ->
6351       let tests = filter_map (
6352         function
6353         | (_, (Always|If _|Unless _), test) -> Some test
6354         | (_, Disabled, _) -> None
6355       ) tests in
6356       let seq = List.concat (List.map seq_of_test tests) in
6357       let cmds_tested = List.map List.hd seq in
6358       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6359   ) all_functions;
6360
6361   List.iter (
6362     fun (name, _, _, _, _, _, _) ->
6363       if not (Hashtbl.mem hash name) then
6364         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6365   ) all_functions;
6366
6367   pr "}\n";
6368   pr "\n";
6369
6370   (* Generate the actual tests.  Note that we generate the tests
6371    * in reverse order, deliberately, so that (in general) the
6372    * newest tests run first.  This makes it quicker and easier to
6373    * debug them.
6374    *)
6375   let test_names =
6376     List.map (
6377       fun (name, _, _, flags, tests, _, _) ->
6378         mapi (generate_one_test name flags) tests
6379     ) (List.rev all_functions) in
6380   let test_names = List.concat test_names in
6381   let nr_tests = List.length test_names in
6382
6383   pr "\
6384 int main (int argc, char *argv[])
6385 {
6386   char c = 0;
6387   unsigned long int n_failed = 0;
6388   const char *filename;
6389   int fd;
6390   int nr_tests, test_num = 0;
6391
6392   setbuf (stdout, NULL);
6393
6394   no_test_warnings ();
6395
6396   g = guestfs_create ();
6397   if (g == NULL) {
6398     printf (\"guestfs_create FAILED\\n\");
6399     exit (EXIT_FAILURE);
6400   }
6401
6402   guestfs_set_error_handler (g, print_error, NULL);
6403
6404   guestfs_set_path (g, \"../appliance\");
6405
6406   filename = \"test1.img\";
6407   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6408   if (fd == -1) {
6409     perror (filename);
6410     exit (EXIT_FAILURE);
6411   }
6412   if (lseek (fd, %d, SEEK_SET) == -1) {
6413     perror (\"lseek\");
6414     close (fd);
6415     unlink (filename);
6416     exit (EXIT_FAILURE);
6417   }
6418   if (write (fd, &c, 1) == -1) {
6419     perror (\"write\");
6420     close (fd);
6421     unlink (filename);
6422     exit (EXIT_FAILURE);
6423   }
6424   if (close (fd) == -1) {
6425     perror (filename);
6426     unlink (filename);
6427     exit (EXIT_FAILURE);
6428   }
6429   if (guestfs_add_drive (g, filename) == -1) {
6430     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6431     exit (EXIT_FAILURE);
6432   }
6433
6434   filename = \"test2.img\";
6435   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6436   if (fd == -1) {
6437     perror (filename);
6438     exit (EXIT_FAILURE);
6439   }
6440   if (lseek (fd, %d, SEEK_SET) == -1) {
6441     perror (\"lseek\");
6442     close (fd);
6443     unlink (filename);
6444     exit (EXIT_FAILURE);
6445   }
6446   if (write (fd, &c, 1) == -1) {
6447     perror (\"write\");
6448     close (fd);
6449     unlink (filename);
6450     exit (EXIT_FAILURE);
6451   }
6452   if (close (fd) == -1) {
6453     perror (filename);
6454     unlink (filename);
6455     exit (EXIT_FAILURE);
6456   }
6457   if (guestfs_add_drive (g, filename) == -1) {
6458     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6459     exit (EXIT_FAILURE);
6460   }
6461
6462   filename = \"test3.img\";
6463   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6464   if (fd == -1) {
6465     perror (filename);
6466     exit (EXIT_FAILURE);
6467   }
6468   if (lseek (fd, %d, SEEK_SET) == -1) {
6469     perror (\"lseek\");
6470     close (fd);
6471     unlink (filename);
6472     exit (EXIT_FAILURE);
6473   }
6474   if (write (fd, &c, 1) == -1) {
6475     perror (\"write\");
6476     close (fd);
6477     unlink (filename);
6478     exit (EXIT_FAILURE);
6479   }
6480   if (close (fd) == -1) {
6481     perror (filename);
6482     unlink (filename);
6483     exit (EXIT_FAILURE);
6484   }
6485   if (guestfs_add_drive (g, filename) == -1) {
6486     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6487     exit (EXIT_FAILURE);
6488   }
6489
6490   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6491     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6492     exit (EXIT_FAILURE);
6493   }
6494
6495   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6496   alarm (600);
6497
6498   if (guestfs_launch (g) == -1) {
6499     printf (\"guestfs_launch FAILED\\n\");
6500     exit (EXIT_FAILURE);
6501   }
6502
6503   /* Cancel previous alarm. */
6504   alarm (0);
6505
6506   nr_tests = %d;
6507
6508 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6509
6510   iteri (
6511     fun i test_name ->
6512       pr "  test_num++;\n";
6513       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6514       pr "  if (%s () == -1) {\n" test_name;
6515       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6516       pr "    n_failed++;\n";
6517       pr "  }\n";
6518   ) test_names;
6519   pr "\n";
6520
6521   pr "  guestfs_close (g);\n";
6522   pr "  unlink (\"test1.img\");\n";
6523   pr "  unlink (\"test2.img\");\n";
6524   pr "  unlink (\"test3.img\");\n";
6525   pr "\n";
6526
6527   pr "  if (n_failed > 0) {\n";
6528   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6529   pr "    exit (EXIT_FAILURE);\n";
6530   pr "  }\n";
6531   pr "\n";
6532
6533   pr "  exit (EXIT_SUCCESS);\n";
6534   pr "}\n"
6535
6536 and generate_one_test name flags i (init, prereq, test) =
6537   let test_name = sprintf "test_%s_%d" name i in
6538
6539   pr "\
6540 static int %s_skip (void)
6541 {
6542   const char *str;
6543
6544   str = getenv (\"TEST_ONLY\");
6545   if (str)
6546     return strstr (str, \"%s\") == NULL;
6547   str = getenv (\"SKIP_%s\");
6548   if (str && STREQ (str, \"1\")) return 1;
6549   str = getenv (\"SKIP_TEST_%s\");
6550   if (str && STREQ (str, \"1\")) return 1;
6551   return 0;
6552 }
6553
6554 " test_name name (String.uppercase test_name) (String.uppercase name);
6555
6556   (match prereq with
6557    | Disabled | Always -> ()
6558    | If code | Unless code ->
6559        pr "static int %s_prereq (void)\n" test_name;
6560        pr "{\n";
6561        pr "  %s\n" code;
6562        pr "}\n";
6563        pr "\n";
6564   );
6565
6566   pr "\
6567 static int %s (void)
6568 {
6569   if (%s_skip ()) {
6570     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6571     return 0;
6572   }
6573
6574 " test_name test_name test_name;
6575
6576   (* Optional functions should only be tested if the relevant
6577    * support is available in the daemon.
6578    *)
6579   List.iter (
6580     function
6581     | Optional group ->
6582         pr "  {\n";
6583         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6584         pr "    int r;\n";
6585         pr "    suppress_error = 1;\n";
6586         pr "    r = guestfs_available (g, (char **) groups);\n";
6587         pr "    suppress_error = 0;\n";
6588         pr "    if (r == -1) {\n";
6589         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6590         pr "      return 0;\n";
6591         pr "    }\n";
6592         pr "  }\n";
6593     | _ -> ()
6594   ) flags;
6595
6596   (match prereq with
6597    | Disabled ->
6598        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6599    | If _ ->
6600        pr "  if (! %s_prereq ()) {\n" test_name;
6601        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6602        pr "    return 0;\n";
6603        pr "  }\n";
6604        pr "\n";
6605        generate_one_test_body name i test_name init test;
6606    | Unless _ ->
6607        pr "  if (%s_prereq ()) {\n" test_name;
6608        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6609        pr "    return 0;\n";
6610        pr "  }\n";
6611        pr "\n";
6612        generate_one_test_body name i test_name init test;
6613    | Always ->
6614        generate_one_test_body name i test_name init test
6615   );
6616
6617   pr "  return 0;\n";
6618   pr "}\n";
6619   pr "\n";
6620   test_name
6621
6622 and generate_one_test_body name i test_name init test =
6623   (match init with
6624    | InitNone (* XXX at some point, InitNone and InitEmpty became
6625                * folded together as the same thing.  Really we should
6626                * make InitNone do nothing at all, but the tests may
6627                * need to be checked to make sure this is OK.
6628                *)
6629    | InitEmpty ->
6630        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6631        List.iter (generate_test_command_call test_name)
6632          [["blockdev_setrw"; "/dev/sda"];
6633           ["umount_all"];
6634           ["lvm_remove_all"]]
6635    | InitPartition ->
6636        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6637        List.iter (generate_test_command_call test_name)
6638          [["blockdev_setrw"; "/dev/sda"];
6639           ["umount_all"];
6640           ["lvm_remove_all"];
6641           ["part_disk"; "/dev/sda"; "mbr"]]
6642    | InitBasicFS ->
6643        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6644        List.iter (generate_test_command_call test_name)
6645          [["blockdev_setrw"; "/dev/sda"];
6646           ["umount_all"];
6647           ["lvm_remove_all"];
6648           ["part_disk"; "/dev/sda"; "mbr"];
6649           ["mkfs"; "ext2"; "/dev/sda1"];
6650           ["mount_options"; ""; "/dev/sda1"; "/"]]
6651    | InitBasicFSonLVM ->
6652        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6653          test_name;
6654        List.iter (generate_test_command_call test_name)
6655          [["blockdev_setrw"; "/dev/sda"];
6656           ["umount_all"];
6657           ["lvm_remove_all"];
6658           ["part_disk"; "/dev/sda"; "mbr"];
6659           ["pvcreate"; "/dev/sda1"];
6660           ["vgcreate"; "VG"; "/dev/sda1"];
6661           ["lvcreate"; "LV"; "VG"; "8"];
6662           ["mkfs"; "ext2"; "/dev/VG/LV"];
6663           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6664    | InitISOFS ->
6665        pr "  /* InitISOFS for %s */\n" test_name;
6666        List.iter (generate_test_command_call test_name)
6667          [["blockdev_setrw"; "/dev/sda"];
6668           ["umount_all"];
6669           ["lvm_remove_all"];
6670           ["mount_ro"; "/dev/sdd"; "/"]]
6671   );
6672
6673   let get_seq_last = function
6674     | [] ->
6675         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6676           test_name
6677     | seq ->
6678         let seq = List.rev seq in
6679         List.rev (List.tl seq), List.hd seq
6680   in
6681
6682   match test with
6683   | TestRun seq ->
6684       pr "  /* TestRun for %s (%d) */\n" name i;
6685       List.iter (generate_test_command_call test_name) seq
6686   | TestOutput (seq, expected) ->
6687       pr "  /* TestOutput for %s (%d) */\n" name i;
6688       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6689       let seq, last = get_seq_last seq in
6690       let test () =
6691         pr "    if (STRNEQ (r, expected)) {\n";
6692         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6693         pr "      return -1;\n";
6694         pr "    }\n"
6695       in
6696       List.iter (generate_test_command_call test_name) seq;
6697       generate_test_command_call ~test test_name last
6698   | TestOutputList (seq, expected) ->
6699       pr "  /* TestOutputList for %s (%d) */\n" name i;
6700       let seq, last = get_seq_last seq in
6701       let test () =
6702         iteri (
6703           fun i str ->
6704             pr "    if (!r[%d]) {\n" i;
6705             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6706             pr "      print_strings (r);\n";
6707             pr "      return -1;\n";
6708             pr "    }\n";
6709             pr "    {\n";
6710             pr "      const char *expected = \"%s\";\n" (c_quote str);
6711             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6712             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6713             pr "        return -1;\n";
6714             pr "      }\n";
6715             pr "    }\n"
6716         ) expected;
6717         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6718         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6719           test_name;
6720         pr "      print_strings (r);\n";
6721         pr "      return -1;\n";
6722         pr "    }\n"
6723       in
6724       List.iter (generate_test_command_call test_name) seq;
6725       generate_test_command_call ~test test_name last
6726   | TestOutputListOfDevices (seq, expected) ->
6727       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6728       let seq, last = get_seq_last seq in
6729       let test () =
6730         iteri (
6731           fun i str ->
6732             pr "    if (!r[%d]) {\n" i;
6733             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6734             pr "      print_strings (r);\n";
6735             pr "      return -1;\n";
6736             pr "    }\n";
6737             pr "    {\n";
6738             pr "      const char *expected = \"%s\";\n" (c_quote str);
6739             pr "      r[%d][5] = 's';\n" i;
6740             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6741             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6742             pr "        return -1;\n";
6743             pr "      }\n";
6744             pr "    }\n"
6745         ) expected;
6746         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6747         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6748           test_name;
6749         pr "      print_strings (r);\n";
6750         pr "      return -1;\n";
6751         pr "    }\n"
6752       in
6753       List.iter (generate_test_command_call test_name) seq;
6754       generate_test_command_call ~test test_name last
6755   | TestOutputInt (seq, expected) ->
6756       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6757       let seq, last = get_seq_last seq in
6758       let test () =
6759         pr "    if (r != %d) {\n" expected;
6760         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6761           test_name expected;
6762         pr "               (int) r);\n";
6763         pr "      return -1;\n";
6764         pr "    }\n"
6765       in
6766       List.iter (generate_test_command_call test_name) seq;
6767       generate_test_command_call ~test test_name last
6768   | TestOutputIntOp (seq, op, expected) ->
6769       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6770       let seq, last = get_seq_last seq in
6771       let test () =
6772         pr "    if (! (r %s %d)) {\n" op expected;
6773         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6774           test_name op expected;
6775         pr "               (int) r);\n";
6776         pr "      return -1;\n";
6777         pr "    }\n"
6778       in
6779       List.iter (generate_test_command_call test_name) seq;
6780       generate_test_command_call ~test test_name last
6781   | TestOutputTrue seq ->
6782       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6783       let seq, last = get_seq_last seq in
6784       let test () =
6785         pr "    if (!r) {\n";
6786         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6787           test_name;
6788         pr "      return -1;\n";
6789         pr "    }\n"
6790       in
6791       List.iter (generate_test_command_call test_name) seq;
6792       generate_test_command_call ~test test_name last
6793   | TestOutputFalse seq ->
6794       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6795       let seq, last = get_seq_last seq in
6796       let test () =
6797         pr "    if (r) {\n";
6798         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6799           test_name;
6800         pr "      return -1;\n";
6801         pr "    }\n"
6802       in
6803       List.iter (generate_test_command_call test_name) seq;
6804       generate_test_command_call ~test test_name last
6805   | TestOutputLength (seq, expected) ->
6806       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6807       let seq, last = get_seq_last seq in
6808       let test () =
6809         pr "    int j;\n";
6810         pr "    for (j = 0; j < %d; ++j)\n" expected;
6811         pr "      if (r[j] == NULL) {\n";
6812         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6813           test_name;
6814         pr "        print_strings (r);\n";
6815         pr "        return -1;\n";
6816         pr "      }\n";
6817         pr "    if (r[j] != NULL) {\n";
6818         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6819           test_name;
6820         pr "      print_strings (r);\n";
6821         pr "      return -1;\n";
6822         pr "    }\n"
6823       in
6824       List.iter (generate_test_command_call test_name) seq;
6825       generate_test_command_call ~test test_name last
6826   | TestOutputBuffer (seq, expected) ->
6827       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6828       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6829       let seq, last = get_seq_last seq in
6830       let len = String.length expected in
6831       let test () =
6832         pr "    if (size != %d) {\n" len;
6833         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6834         pr "      return -1;\n";
6835         pr "    }\n";
6836         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6837         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6838         pr "      return -1;\n";
6839         pr "    }\n"
6840       in
6841       List.iter (generate_test_command_call test_name) seq;
6842       generate_test_command_call ~test test_name last
6843   | TestOutputStruct (seq, checks) ->
6844       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6845       let seq, last = get_seq_last seq in
6846       let test () =
6847         List.iter (
6848           function
6849           | CompareWithInt (field, expected) ->
6850               pr "    if (r->%s != %d) {\n" field expected;
6851               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6852                 test_name field expected;
6853               pr "               (int) r->%s);\n" field;
6854               pr "      return -1;\n";
6855               pr "    }\n"
6856           | CompareWithIntOp (field, op, expected) ->
6857               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6858               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6859                 test_name field op expected;
6860               pr "               (int) r->%s);\n" field;
6861               pr "      return -1;\n";
6862               pr "    }\n"
6863           | CompareWithString (field, expected) ->
6864               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6865               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6866                 test_name field expected;
6867               pr "               r->%s);\n" field;
6868               pr "      return -1;\n";
6869               pr "    }\n"
6870           | CompareFieldsIntEq (field1, field2) ->
6871               pr "    if (r->%s != r->%s) {\n" field1 field2;
6872               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6873                 test_name field1 field2;
6874               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6875               pr "      return -1;\n";
6876               pr "    }\n"
6877           | CompareFieldsStrEq (field1, field2) ->
6878               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6879               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6880                 test_name field1 field2;
6881               pr "               r->%s, r->%s);\n" field1 field2;
6882               pr "      return -1;\n";
6883               pr "    }\n"
6884         ) checks
6885       in
6886       List.iter (generate_test_command_call test_name) seq;
6887       generate_test_command_call ~test test_name last
6888   | TestLastFail seq ->
6889       pr "  /* TestLastFail for %s (%d) */\n" name i;
6890       let seq, last = get_seq_last seq in
6891       List.iter (generate_test_command_call test_name) seq;
6892       generate_test_command_call test_name ~expect_error:true last
6893
6894 (* Generate the code to run a command, leaving the result in 'r'.
6895  * If you expect to get an error then you should set expect_error:true.
6896  *)
6897 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6898   match cmd with
6899   | [] -> assert false
6900   | name :: args ->
6901       (* Look up the command to find out what args/ret it has. *)
6902       let style =
6903         try
6904           let _, style, _, _, _, _, _ =
6905             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6906           style
6907         with Not_found ->
6908           failwithf "%s: in test, command %s was not found" test_name name in
6909
6910       if List.length (snd style) <> List.length args then
6911         failwithf "%s: in test, wrong number of args given to %s"
6912           test_name name;
6913
6914       pr "  {\n";
6915
6916       List.iter (
6917         function
6918         | OptString n, "NULL" -> ()
6919         | Pathname n, arg
6920         | Device n, arg
6921         | Dev_or_Path n, arg
6922         | String n, arg
6923         | OptString n, arg ->
6924             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6925         | Int _, _
6926         | Int64 _, _
6927         | Bool _, _
6928         | FileIn _, _ | FileOut _, _ -> ()
6929         | StringList n, "" | DeviceList n, "" ->
6930             pr "    const char *const %s[1] = { NULL };\n" n
6931         | StringList n, arg | DeviceList n, arg ->
6932             let strs = string_split " " arg in
6933             iteri (
6934               fun i str ->
6935                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6936             ) strs;
6937             pr "    const char *const %s[] = {\n" n;
6938             iteri (
6939               fun i _ -> pr "      %s_%d,\n" n i
6940             ) strs;
6941             pr "      NULL\n";
6942             pr "    };\n";
6943       ) (List.combine (snd style) args);
6944
6945       let error_code =
6946         match fst style with
6947         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6948         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6949         | RConstString _ | RConstOptString _ ->
6950             pr "    const char *r;\n"; "NULL"
6951         | RString _ -> pr "    char *r;\n"; "NULL"
6952         | RStringList _ | RHashtable _ ->
6953             pr "    char **r;\n";
6954             pr "    int i;\n";
6955             "NULL"
6956         | RStruct (_, typ) ->
6957             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6958         | RStructList (_, typ) ->
6959             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6960         | RBufferOut _ ->
6961             pr "    char *r;\n";
6962             pr "    size_t size;\n";
6963             "NULL" in
6964
6965       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6966       pr "    r = guestfs_%s (g" name;
6967
6968       (* Generate the parameters. *)
6969       List.iter (
6970         function
6971         | OptString _, "NULL" -> pr ", NULL"
6972         | Pathname n, _
6973         | Device n, _ | Dev_or_Path n, _
6974         | String n, _
6975         | OptString n, _ ->
6976             pr ", %s" n
6977         | FileIn _, arg | FileOut _, arg ->
6978             pr ", \"%s\"" (c_quote arg)
6979         | StringList n, _ | DeviceList n, _ ->
6980             pr ", (char **) %s" n
6981         | Int _, arg ->
6982             let i =
6983               try int_of_string arg
6984               with Failure "int_of_string" ->
6985                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6986             pr ", %d" i
6987         | Int64 _, arg ->
6988             let i =
6989               try Int64.of_string arg
6990               with Failure "int_of_string" ->
6991                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6992             pr ", %Ld" i
6993         | Bool _, arg ->
6994             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6995       ) (List.combine (snd style) args);
6996
6997       (match fst style with
6998        | RBufferOut _ -> pr ", &size"
6999        | _ -> ()
7000       );
7001
7002       pr ");\n";
7003
7004       if not expect_error then
7005         pr "    if (r == %s)\n" error_code
7006       else
7007         pr "    if (r != %s)\n" error_code;
7008       pr "      return -1;\n";
7009
7010       (* Insert the test code. *)
7011       (match test with
7012        | None -> ()
7013        | Some f -> f ()
7014       );
7015
7016       (match fst style with
7017        | RErr | RInt _ | RInt64 _ | RBool _
7018        | RConstString _ | RConstOptString _ -> ()
7019        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7020        | RStringList _ | RHashtable _ ->
7021            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7022            pr "      free (r[i]);\n";
7023            pr "    free (r);\n"
7024        | RStruct (_, typ) ->
7025            pr "    guestfs_free_%s (r);\n" typ
7026        | RStructList (_, typ) ->
7027            pr "    guestfs_free_%s_list (r);\n" typ
7028       );
7029
7030       pr "  }\n"
7031
7032 and c_quote str =
7033   let str = replace_str str "\r" "\\r" in
7034   let str = replace_str str "\n" "\\n" in
7035   let str = replace_str str "\t" "\\t" in
7036   let str = replace_str str "\000" "\\0" in
7037   str
7038
7039 (* Generate a lot of different functions for guestfish. *)
7040 and generate_fish_cmds () =
7041   generate_header CStyle GPLv2plus;
7042
7043   let all_functions =
7044     List.filter (
7045       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7046     ) all_functions in
7047   let all_functions_sorted =
7048     List.filter (
7049       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7050     ) all_functions_sorted in
7051
7052   pr "#include <config.h>\n";
7053   pr "\n";
7054   pr "#include <stdio.h>\n";
7055   pr "#include <stdlib.h>\n";
7056   pr "#include <string.h>\n";
7057   pr "#include <inttypes.h>\n";
7058   pr "\n";
7059   pr "#include <guestfs.h>\n";
7060   pr "#include \"c-ctype.h\"\n";
7061   pr "#include \"full-write.h\"\n";
7062   pr "#include \"xstrtol.h\"\n";
7063   pr "#include \"fish.h\"\n";
7064   pr "\n";
7065
7066   (* list_commands function, which implements guestfish -h *)
7067   pr "void list_commands (void)\n";
7068   pr "{\n";
7069   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7070   pr "  list_builtin_commands ();\n";
7071   List.iter (
7072     fun (name, _, _, flags, _, shortdesc, _) ->
7073       let name = replace_char name '_' '-' in
7074       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7075         name shortdesc
7076   ) all_functions_sorted;
7077   pr "  printf (\"    %%s\\n\",";
7078   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7079   pr "}\n";
7080   pr "\n";
7081
7082   (* display_command function, which implements guestfish -h cmd *)
7083   pr "void display_command (const char *cmd)\n";
7084   pr "{\n";
7085   List.iter (
7086     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7087       let name2 = replace_char name '_' '-' in
7088       let alias =
7089         try find_map (function FishAlias n -> Some n | _ -> None) flags
7090         with Not_found -> name in
7091       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7092       let synopsis =
7093         match snd style with
7094         | [] -> name2
7095         | args ->
7096             sprintf "%s %s"
7097               name2 (String.concat " " (List.map name_of_argt args)) in
7098
7099       let warnings =
7100         if List.mem ProtocolLimitWarning flags then
7101           ("\n\n" ^ protocol_limit_warning)
7102         else "" in
7103
7104       (* For DangerWillRobinson commands, we should probably have
7105        * guestfish prompt before allowing you to use them (especially
7106        * in interactive mode). XXX
7107        *)
7108       let warnings =
7109         warnings ^
7110           if List.mem DangerWillRobinson flags then
7111             ("\n\n" ^ danger_will_robinson)
7112           else "" in
7113
7114       let warnings =
7115         warnings ^
7116           match deprecation_notice flags with
7117           | None -> ""
7118           | Some txt -> "\n\n" ^ txt in
7119
7120       let describe_alias =
7121         if name <> alias then
7122           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7123         else "" in
7124
7125       pr "  if (";
7126       pr "STRCASEEQ (cmd, \"%s\")" name;
7127       if name <> name2 then
7128         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7129       if name <> alias then
7130         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7131       pr ")\n";
7132       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7133         name2 shortdesc
7134         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7135          "=head1 DESCRIPTION\n\n" ^
7136          longdesc ^ warnings ^ describe_alias);
7137       pr "  else\n"
7138   ) all_functions;
7139   pr "    display_builtin_command (cmd);\n";
7140   pr "}\n";
7141   pr "\n";
7142
7143   let emit_print_list_function typ =
7144     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7145       typ typ typ;
7146     pr "{\n";
7147     pr "  unsigned int i;\n";
7148     pr "\n";
7149     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7150     pr "    printf (\"[%%d] = {\\n\", i);\n";
7151     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7152     pr "    printf (\"}\\n\");\n";
7153     pr "  }\n";
7154     pr "}\n";
7155     pr "\n";
7156   in
7157
7158   (* print_* functions *)
7159   List.iter (
7160     fun (typ, cols) ->
7161       let needs_i =
7162         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7163
7164       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7165       pr "{\n";
7166       if needs_i then (
7167         pr "  unsigned int i;\n";
7168         pr "\n"
7169       );
7170       List.iter (
7171         function
7172         | name, FString ->
7173             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7174         | name, FUUID ->
7175             pr "  printf (\"%%s%s: \", indent);\n" name;
7176             pr "  for (i = 0; i < 32; ++i)\n";
7177             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7178             pr "  printf (\"\\n\");\n"
7179         | name, FBuffer ->
7180             pr "  printf (\"%%s%s: \", indent);\n" name;
7181             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7182             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7183             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7184             pr "    else\n";
7185             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7186             pr "  printf (\"\\n\");\n"
7187         | name, (FUInt64|FBytes) ->
7188             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7189               name typ name
7190         | name, FInt64 ->
7191             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7192               name typ name
7193         | name, FUInt32 ->
7194             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7195               name typ name
7196         | name, FInt32 ->
7197             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7198               name typ name
7199         | name, FChar ->
7200             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7201               name typ name
7202         | name, FOptPercent ->
7203             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7204               typ name name typ name;
7205             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7206       ) cols;
7207       pr "}\n";
7208       pr "\n";
7209   ) structs;
7210
7211   (* Emit a print_TYPE_list function definition only if that function is used. *)
7212   List.iter (
7213     function
7214     | typ, (RStructListOnly | RStructAndList) ->
7215         (* generate the function for typ *)
7216         emit_print_list_function typ
7217     | typ, _ -> () (* empty *)
7218   ) (rstructs_used_by all_functions);
7219
7220   (* Emit a print_TYPE function definition only if that function is used. *)
7221   List.iter (
7222     function
7223     | typ, (RStructOnly | RStructAndList) ->
7224         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7225         pr "{\n";
7226         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7227         pr "}\n";
7228         pr "\n";
7229     | typ, _ -> () (* empty *)
7230   ) (rstructs_used_by all_functions);
7231
7232   (* run_<action> actions *)
7233   List.iter (
7234     fun (name, style, _, flags, _, _, _) ->
7235       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7236       pr "{\n";
7237       (match fst style with
7238        | RErr
7239        | RInt _
7240        | RBool _ -> pr "  int r;\n"
7241        | RInt64 _ -> pr "  int64_t r;\n"
7242        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7243        | RString _ -> pr "  char *r;\n"
7244        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7245        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7246        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7247        | RBufferOut _ ->
7248            pr "  char *r;\n";
7249            pr "  size_t size;\n";
7250       );
7251       List.iter (
7252         function
7253         | Device n
7254         | String n
7255         | OptString n
7256         | FileIn n
7257         | FileOut n -> pr "  const char *%s;\n" n
7258         | Pathname n
7259         | Dev_or_Path n -> pr "  char *%s;\n" n
7260         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7261         | Bool n -> pr "  int %s;\n" n
7262         | Int n -> pr "  int %s;\n" n
7263         | Int64 n -> pr "  int64_t %s;\n" n
7264       ) (snd style);
7265
7266       (* Check and convert parameters. *)
7267       let argc_expected = List.length (snd style) in
7268       pr "  if (argc != %d) {\n" argc_expected;
7269       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7270         argc_expected;
7271       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7272       pr "    return -1;\n";
7273       pr "  }\n";
7274
7275       let parse_integer fn fntyp rtyp range name i =
7276         pr "  {\n";
7277         pr "    strtol_error xerr;\n";
7278         pr "    %s r;\n" fntyp;
7279         pr "\n";
7280         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7281         pr "    if (xerr != LONGINT_OK) {\n";
7282         pr "      fprintf (stderr,\n";
7283         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7284         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7285         pr "      return -1;\n";
7286         pr "    }\n";
7287         (match range with
7288          | None -> ()
7289          | Some (min, max, comment) ->
7290              pr "    /* %s */\n" comment;
7291              pr "    if (r < %s || r > %s) {\n" min max;
7292              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7293                name;
7294              pr "      return -1;\n";
7295              pr "    }\n";
7296              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7297         );
7298         pr "    %s = r;\n" name;
7299         pr "  }\n";
7300       in
7301
7302       iteri (
7303         fun i ->
7304           function
7305           | Device name
7306           | String name ->
7307               pr "  %s = argv[%d];\n" name i
7308           | Pathname name
7309           | Dev_or_Path name ->
7310               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7311               pr "  if (%s == NULL) return -1;\n" name
7312           | OptString name ->
7313               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7314                 name i i
7315           | FileIn name ->
7316               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7317                 name i i
7318           | FileOut name ->
7319               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7320                 name i i
7321           | StringList name | DeviceList name ->
7322               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7323               pr "  if (%s == NULL) return -1;\n" name;
7324           | Bool name ->
7325               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7326           | Int name ->
7327               let range =
7328                 let min = "(-(2LL<<30))"
7329                 and max = "((2LL<<30)-1)"
7330                 and comment =
7331                   "The Int type in the generator is a signed 31 bit int." in
7332                 Some (min, max, comment) in
7333               parse_integer "xstrtoll" "long long" "int" range name i
7334           | Int64 name ->
7335               parse_integer "xstrtoll" "long long" "int64_t" None name i
7336       ) (snd style);
7337
7338       (* Call C API function. *)
7339       let fn =
7340         try find_map (function FishAction n -> Some n | _ -> None) flags
7341         with Not_found -> sprintf "guestfs_%s" name in
7342       pr "  r = %s " fn;
7343       generate_c_call_args ~handle:"g" style;
7344       pr ";\n";
7345
7346       List.iter (
7347         function
7348         | Device name | String name
7349         | OptString name | FileIn name | FileOut name | Bool name
7350         | Int name | Int64 name -> ()
7351         | Pathname name | Dev_or_Path name ->
7352             pr "  free (%s);\n" name
7353         | StringList name | DeviceList name ->
7354             pr "  free_strings (%s);\n" name
7355       ) (snd style);
7356
7357       (* Check return value for errors and display command results. *)
7358       (match fst style with
7359        | RErr -> pr "  return r;\n"
7360        | RInt _ ->
7361            pr "  if (r == -1) return -1;\n";
7362            pr "  printf (\"%%d\\n\", r);\n";
7363            pr "  return 0;\n"
7364        | RInt64 _ ->
7365            pr "  if (r == -1) return -1;\n";
7366            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7367            pr "  return 0;\n"
7368        | RBool _ ->
7369            pr "  if (r == -1) return -1;\n";
7370            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7371            pr "  return 0;\n"
7372        | RConstString _ ->
7373            pr "  if (r == NULL) return -1;\n";
7374            pr "  printf (\"%%s\\n\", r);\n";
7375            pr "  return 0;\n"
7376        | RConstOptString _ ->
7377            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7378            pr "  return 0;\n"
7379        | RString _ ->
7380            pr "  if (r == NULL) return -1;\n";
7381            pr "  printf (\"%%s\\n\", r);\n";
7382            pr "  free (r);\n";
7383            pr "  return 0;\n"
7384        | RStringList _ ->
7385            pr "  if (r == NULL) return -1;\n";
7386            pr "  print_strings (r);\n";
7387            pr "  free_strings (r);\n";
7388            pr "  return 0;\n"
7389        | RStruct (_, typ) ->
7390            pr "  if (r == NULL) return -1;\n";
7391            pr "  print_%s (r);\n" typ;
7392            pr "  guestfs_free_%s (r);\n" typ;
7393            pr "  return 0;\n"
7394        | RStructList (_, typ) ->
7395            pr "  if (r == NULL) return -1;\n";
7396            pr "  print_%s_list (r);\n" typ;
7397            pr "  guestfs_free_%s_list (r);\n" typ;
7398            pr "  return 0;\n"
7399        | RHashtable _ ->
7400            pr "  if (r == NULL) return -1;\n";
7401            pr "  print_table (r);\n";
7402            pr "  free_strings (r);\n";
7403            pr "  return 0;\n"
7404        | RBufferOut _ ->
7405            pr "  if (r == NULL) return -1;\n";
7406            pr "  if (full_write (1, r, size) != size) {\n";
7407            pr "    perror (\"write\");\n";
7408            pr "    free (r);\n";
7409            pr "    return -1;\n";
7410            pr "  }\n";
7411            pr "  free (r);\n";
7412            pr "  return 0;\n"
7413       );
7414       pr "}\n";
7415       pr "\n"
7416   ) all_functions;
7417
7418   (* run_action function *)
7419   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7420   pr "{\n";
7421   List.iter (
7422     fun (name, _, _, flags, _, _, _) ->
7423       let name2 = replace_char name '_' '-' in
7424       let alias =
7425         try find_map (function FishAlias n -> Some n | _ -> None) flags
7426         with Not_found -> name in
7427       pr "  if (";
7428       pr "STRCASEEQ (cmd, \"%s\")" name;
7429       if name <> name2 then
7430         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7431       if name <> alias then
7432         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7433       pr ")\n";
7434       pr "    return run_%s (cmd, argc, argv);\n" name;
7435       pr "  else\n";
7436   ) all_functions;
7437   pr "    {\n";
7438   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7439   pr "      if (command_num == 1)\n";
7440   pr "        extended_help_message ();\n";
7441   pr "      return -1;\n";
7442   pr "    }\n";
7443   pr "  return 0;\n";
7444   pr "}\n";
7445   pr "\n"
7446
7447 (* Readline completion for guestfish. *)
7448 and generate_fish_completion () =
7449   generate_header CStyle GPLv2plus;
7450
7451   let all_functions =
7452     List.filter (
7453       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7454     ) all_functions in
7455
7456   pr "\
7457 #include <config.h>
7458
7459 #include <stdio.h>
7460 #include <stdlib.h>
7461 #include <string.h>
7462
7463 #ifdef HAVE_LIBREADLINE
7464 #include <readline/readline.h>
7465 #endif
7466
7467 #include \"fish.h\"
7468
7469 #ifdef HAVE_LIBREADLINE
7470
7471 static const char *const commands[] = {
7472   BUILTIN_COMMANDS_FOR_COMPLETION,
7473 ";
7474
7475   (* Get the commands, including the aliases.  They don't need to be
7476    * sorted - the generator() function just does a dumb linear search.
7477    *)
7478   let commands =
7479     List.map (
7480       fun (name, _, _, flags, _, _, _) ->
7481         let name2 = replace_char name '_' '-' in
7482         let alias =
7483           try find_map (function FishAlias n -> Some n | _ -> None) flags
7484           with Not_found -> name in
7485
7486         if name <> alias then [name2; alias] else [name2]
7487     ) all_functions in
7488   let commands = List.flatten commands in
7489
7490   List.iter (pr "  \"%s\",\n") commands;
7491
7492   pr "  NULL
7493 };
7494
7495 static char *
7496 generator (const char *text, int state)
7497 {
7498   static int index, len;
7499   const char *name;
7500
7501   if (!state) {
7502     index = 0;
7503     len = strlen (text);
7504   }
7505
7506   rl_attempted_completion_over = 1;
7507
7508   while ((name = commands[index]) != NULL) {
7509     index++;
7510     if (STRCASEEQLEN (name, text, len))
7511       return strdup (name);
7512   }
7513
7514   return NULL;
7515 }
7516
7517 #endif /* HAVE_LIBREADLINE */
7518
7519 #ifdef HAVE_RL_COMPLETION_MATCHES
7520 #define RL_COMPLETION_MATCHES rl_completion_matches
7521 #else
7522 #ifdef HAVE_COMPLETION_MATCHES
7523 #define RL_COMPLETION_MATCHES completion_matches
7524 #endif
7525 #endif /* else just fail if we don't have either symbol */
7526
7527 char **
7528 do_completion (const char *text, int start, int end)
7529 {
7530   char **matches = NULL;
7531
7532 #ifdef HAVE_LIBREADLINE
7533   rl_completion_append_character = ' ';
7534
7535   if (start == 0)
7536     matches = RL_COMPLETION_MATCHES (text, generator);
7537   else if (complete_dest_paths)
7538     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7539 #endif
7540
7541   return matches;
7542 }
7543 ";
7544
7545 (* Generate the POD documentation for guestfish. *)
7546 and generate_fish_actions_pod () =
7547   let all_functions_sorted =
7548     List.filter (
7549       fun (_, _, _, flags, _, _, _) ->
7550         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7551     ) all_functions_sorted in
7552
7553   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7554
7555   List.iter (
7556     fun (name, style, _, flags, _, _, longdesc) ->
7557       let longdesc =
7558         Str.global_substitute rex (
7559           fun s ->
7560             let sub =
7561               try Str.matched_group 1 s
7562               with Not_found ->
7563                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7564             "C<" ^ replace_char sub '_' '-' ^ ">"
7565         ) longdesc in
7566       let name = replace_char name '_' '-' in
7567       let alias =
7568         try find_map (function FishAlias n -> Some n | _ -> None) flags
7569         with Not_found -> name in
7570
7571       pr "=head2 %s" name;
7572       if name <> alias then
7573         pr " | %s" alias;
7574       pr "\n";
7575       pr "\n";
7576       pr " %s" name;
7577       List.iter (
7578         function
7579         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7580         | OptString n -> pr " %s" n
7581         | StringList n | DeviceList n -> pr " '%s ...'" n
7582         | Bool _ -> pr " true|false"
7583         | Int n -> pr " %s" n
7584         | Int64 n -> pr " %s" n
7585         | FileIn n | FileOut n -> pr " (%s|-)" n
7586       ) (snd style);
7587       pr "\n";
7588       pr "\n";
7589       pr "%s\n\n" longdesc;
7590
7591       if List.exists (function FileIn _ | FileOut _ -> true
7592                       | _ -> false) (snd style) then
7593         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7594
7595       if List.mem ProtocolLimitWarning flags then
7596         pr "%s\n\n" protocol_limit_warning;
7597
7598       if List.mem DangerWillRobinson flags then
7599         pr "%s\n\n" danger_will_robinson;
7600
7601       match deprecation_notice flags with
7602       | None -> ()
7603       | Some txt -> pr "%s\n\n" txt
7604   ) all_functions_sorted
7605
7606 (* Generate a C function prototype. *)
7607 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7608     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7609     ?(prefix = "")
7610     ?handle name style =
7611   if extern then pr "extern ";
7612   if static then pr "static ";
7613   (match fst style with
7614    | RErr -> pr "int "
7615    | RInt _ -> pr "int "
7616    | RInt64 _ -> pr "int64_t "
7617    | RBool _ -> pr "int "
7618    | RConstString _ | RConstOptString _ -> pr "const char *"
7619    | RString _ | RBufferOut _ -> pr "char *"
7620    | RStringList _ | RHashtable _ -> pr "char **"
7621    | RStruct (_, typ) ->
7622        if not in_daemon then pr "struct guestfs_%s *" typ
7623        else pr "guestfs_int_%s *" typ
7624    | RStructList (_, typ) ->
7625        if not in_daemon then pr "struct guestfs_%s_list *" typ
7626        else pr "guestfs_int_%s_list *" typ
7627   );
7628   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7629   pr "%s%s (" prefix name;
7630   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7631     pr "void"
7632   else (
7633     let comma = ref false in
7634     (match handle with
7635      | None -> ()
7636      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7637     );
7638     let next () =
7639       if !comma then (
7640         if single_line then pr ", " else pr ",\n\t\t"
7641       );
7642       comma := true
7643     in
7644     List.iter (
7645       function
7646       | Pathname n
7647       | Device n | Dev_or_Path n
7648       | String n
7649       | OptString n ->
7650           next ();
7651           pr "const char *%s" n
7652       | StringList n | DeviceList n ->
7653           next ();
7654           pr "char *const *%s" n
7655       | Bool n -> next (); pr "int %s" n
7656       | Int n -> next (); pr "int %s" n
7657       | Int64 n -> next (); pr "int64_t %s" n
7658       | FileIn n
7659       | FileOut n ->
7660           if not in_daemon then (next (); pr "const char *%s" n)
7661     ) (snd style);
7662     if is_RBufferOut then (next (); pr "size_t *size_r");
7663   );
7664   pr ")";
7665   if semicolon then pr ";";
7666   if newline then pr "\n"
7667
7668 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7669 and generate_c_call_args ?handle ?(decl = false) style =
7670   pr "(";
7671   let comma = ref false in
7672   let next () =
7673     if !comma then pr ", ";
7674     comma := true
7675   in
7676   (match handle with
7677    | None -> ()
7678    | Some handle -> pr "%s" handle; comma := true
7679   );
7680   List.iter (
7681     fun arg ->
7682       next ();
7683       pr "%s" (name_of_argt arg)
7684   ) (snd style);
7685   (* For RBufferOut calls, add implicit &size parameter. *)
7686   if not decl then (
7687     match fst style with
7688     | RBufferOut _ ->
7689         next ();
7690         pr "&size"
7691     | _ -> ()
7692   );
7693   pr ")"
7694
7695 (* Generate the OCaml bindings interface. *)
7696 and generate_ocaml_mli () =
7697   generate_header OCamlStyle LGPLv2plus;
7698
7699   pr "\
7700 (** For API documentation you should refer to the C API
7701     in the guestfs(3) manual page.  The OCaml API uses almost
7702     exactly the same calls. *)
7703
7704 type t
7705 (** A [guestfs_h] handle. *)
7706
7707 exception Error of string
7708 (** This exception is raised when there is an error. *)
7709
7710 exception Handle_closed of string
7711 (** This exception is raised if you use a {!Guestfs.t} handle
7712     after calling {!close} on it.  The string is the name of
7713     the function. *)
7714
7715 val create : unit -> t
7716 (** Create a {!Guestfs.t} handle. *)
7717
7718 val close : t -> unit
7719 (** Close the {!Guestfs.t} handle and free up all resources used
7720     by it immediately.
7721
7722     Handles are closed by the garbage collector when they become
7723     unreferenced, but callers can call this in order to provide
7724     predictable cleanup. *)
7725
7726 ";
7727   generate_ocaml_structure_decls ();
7728
7729   (* The actions. *)
7730   List.iter (
7731     fun (name, style, _, _, _, shortdesc, _) ->
7732       generate_ocaml_prototype name style;
7733       pr "(** %s *)\n" shortdesc;
7734       pr "\n"
7735   ) all_functions_sorted
7736
7737 (* Generate the OCaml bindings implementation. *)
7738 and generate_ocaml_ml () =
7739   generate_header OCamlStyle LGPLv2plus;
7740
7741   pr "\
7742 type t
7743
7744 exception Error of string
7745 exception Handle_closed of string
7746
7747 external create : unit -> t = \"ocaml_guestfs_create\"
7748 external close : t -> unit = \"ocaml_guestfs_close\"
7749
7750 (* Give the exceptions names, so they can be raised from the C code. *)
7751 let () =
7752   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7753   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7754
7755 ";
7756
7757   generate_ocaml_structure_decls ();
7758
7759   (* The actions. *)
7760   List.iter (
7761     fun (name, style, _, _, _, shortdesc, _) ->
7762       generate_ocaml_prototype ~is_external:true name style;
7763   ) all_functions_sorted
7764
7765 (* Generate the OCaml bindings C implementation. *)
7766 and generate_ocaml_c () =
7767   generate_header CStyle LGPLv2plus;
7768
7769   pr "\
7770 #include <stdio.h>
7771 #include <stdlib.h>
7772 #include <string.h>
7773
7774 #include <caml/config.h>
7775 #include <caml/alloc.h>
7776 #include <caml/callback.h>
7777 #include <caml/fail.h>
7778 #include <caml/memory.h>
7779 #include <caml/mlvalues.h>
7780 #include <caml/signals.h>
7781
7782 #include <guestfs.h>
7783
7784 #include \"guestfs_c.h\"
7785
7786 /* Copy a hashtable of string pairs into an assoc-list.  We return
7787  * the list in reverse order, but hashtables aren't supposed to be
7788  * ordered anyway.
7789  */
7790 static CAMLprim value
7791 copy_table (char * const * argv)
7792 {
7793   CAMLparam0 ();
7794   CAMLlocal5 (rv, pairv, kv, vv, cons);
7795   int i;
7796
7797   rv = Val_int (0);
7798   for (i = 0; argv[i] != NULL; i += 2) {
7799     kv = caml_copy_string (argv[i]);
7800     vv = caml_copy_string (argv[i+1]);
7801     pairv = caml_alloc (2, 0);
7802     Store_field (pairv, 0, kv);
7803     Store_field (pairv, 1, vv);
7804     cons = caml_alloc (2, 0);
7805     Store_field (cons, 1, rv);
7806     rv = cons;
7807     Store_field (cons, 0, pairv);
7808   }
7809
7810   CAMLreturn (rv);
7811 }
7812
7813 ";
7814
7815   (* Struct copy functions. *)
7816
7817   let emit_ocaml_copy_list_function typ =
7818     pr "static CAMLprim value\n";
7819     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7820     pr "{\n";
7821     pr "  CAMLparam0 ();\n";
7822     pr "  CAMLlocal2 (rv, v);\n";
7823     pr "  unsigned int i;\n";
7824     pr "\n";
7825     pr "  if (%ss->len == 0)\n" typ;
7826     pr "    CAMLreturn (Atom (0));\n";
7827     pr "  else {\n";
7828     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7829     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7830     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7831     pr "      caml_modify (&Field (rv, i), v);\n";
7832     pr "    }\n";
7833     pr "    CAMLreturn (rv);\n";
7834     pr "  }\n";
7835     pr "}\n";
7836     pr "\n";
7837   in
7838
7839   List.iter (
7840     fun (typ, cols) ->
7841       let has_optpercent_col =
7842         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7843
7844       pr "static CAMLprim value\n";
7845       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7846       pr "{\n";
7847       pr "  CAMLparam0 ();\n";
7848       if has_optpercent_col then
7849         pr "  CAMLlocal3 (rv, v, v2);\n"
7850       else
7851         pr "  CAMLlocal2 (rv, v);\n";
7852       pr "\n";
7853       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7854       iteri (
7855         fun i col ->
7856           (match col with
7857            | name, FString ->
7858                pr "  v = caml_copy_string (%s->%s);\n" typ name
7859            | name, FBuffer ->
7860                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7861                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7862                  typ name typ name
7863            | name, FUUID ->
7864                pr "  v = caml_alloc_string (32);\n";
7865                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7866            | name, (FBytes|FInt64|FUInt64) ->
7867                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7868            | name, (FInt32|FUInt32) ->
7869                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7870            | name, FOptPercent ->
7871                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7872                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7873                pr "    v = caml_alloc (1, 0);\n";
7874                pr "    Store_field (v, 0, v2);\n";
7875                pr "  } else /* None */\n";
7876                pr "    v = Val_int (0);\n";
7877            | name, FChar ->
7878                pr "  v = Val_int (%s->%s);\n" typ name
7879           );
7880           pr "  Store_field (rv, %d, v);\n" i
7881       ) cols;
7882       pr "  CAMLreturn (rv);\n";
7883       pr "}\n";
7884       pr "\n";
7885   ) structs;
7886
7887   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7888   List.iter (
7889     function
7890     | typ, (RStructListOnly | RStructAndList) ->
7891         (* generate the function for typ *)
7892         emit_ocaml_copy_list_function typ
7893     | typ, _ -> () (* empty *)
7894   ) (rstructs_used_by all_functions);
7895
7896   (* The wrappers. *)
7897   List.iter (
7898     fun (name, style, _, _, _, _, _) ->
7899       pr "/* Automatically generated wrapper for function\n";
7900       pr " * ";
7901       generate_ocaml_prototype name style;
7902       pr " */\n";
7903       pr "\n";
7904
7905       let params =
7906         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7907
7908       let needs_extra_vs =
7909         match fst style with RConstOptString _ -> true | _ -> false in
7910
7911       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7912       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7913       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7914       pr "\n";
7915
7916       pr "CAMLprim value\n";
7917       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7918       List.iter (pr ", value %s") (List.tl params);
7919       pr ")\n";
7920       pr "{\n";
7921
7922       (match params with
7923        | [p1; p2; p3; p4; p5] ->
7924            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7925        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7926            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7927            pr "  CAMLxparam%d (%s);\n"
7928              (List.length rest) (String.concat ", " rest)
7929        | ps ->
7930            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7931       );
7932       if not needs_extra_vs then
7933         pr "  CAMLlocal1 (rv);\n"
7934       else
7935         pr "  CAMLlocal3 (rv, v, v2);\n";
7936       pr "\n";
7937
7938       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7939       pr "  if (g == NULL)\n";
7940       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7941       pr "\n";
7942
7943       List.iter (
7944         function
7945         | Pathname n
7946         | Device n | Dev_or_Path n
7947         | String n
7948         | FileIn n
7949         | FileOut n ->
7950             pr "  const char *%s = String_val (%sv);\n" n n
7951         | OptString n ->
7952             pr "  const char *%s =\n" n;
7953             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7954               n n
7955         | StringList n | DeviceList n ->
7956             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7957         | Bool n ->
7958             pr "  int %s = Bool_val (%sv);\n" n n
7959         | Int n ->
7960             pr "  int %s = Int_val (%sv);\n" n n
7961         | Int64 n ->
7962             pr "  int64_t %s = Int64_val (%sv);\n" n n
7963       ) (snd style);
7964       let error_code =
7965         match fst style with
7966         | RErr -> pr "  int r;\n"; "-1"
7967         | RInt _ -> pr "  int r;\n"; "-1"
7968         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7969         | RBool _ -> pr "  int r;\n"; "-1"
7970         | RConstString _ | RConstOptString _ ->
7971             pr "  const char *r;\n"; "NULL"
7972         | RString _ -> pr "  char *r;\n"; "NULL"
7973         | RStringList _ ->
7974             pr "  int i;\n";
7975             pr "  char **r;\n";
7976             "NULL"
7977         | RStruct (_, typ) ->
7978             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7979         | RStructList (_, typ) ->
7980             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7981         | RHashtable _ ->
7982             pr "  int i;\n";
7983             pr "  char **r;\n";
7984             "NULL"
7985         | RBufferOut _ ->
7986             pr "  char *r;\n";
7987             pr "  size_t size;\n";
7988             "NULL" in
7989       pr "\n";
7990
7991       pr "  caml_enter_blocking_section ();\n";
7992       pr "  r = guestfs_%s " name;
7993       generate_c_call_args ~handle:"g" style;
7994       pr ";\n";
7995       pr "  caml_leave_blocking_section ();\n";
7996
7997       List.iter (
7998         function
7999         | StringList n | DeviceList n ->
8000             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8001         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8002         | Bool _ | Int _ | Int64 _
8003         | FileIn _ | FileOut _ -> ()
8004       ) (snd style);
8005
8006       pr "  if (r == %s)\n" error_code;
8007       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8008       pr "\n";
8009
8010       (match fst style with
8011        | RErr -> pr "  rv = Val_unit;\n"
8012        | RInt _ -> pr "  rv = Val_int (r);\n"
8013        | RInt64 _ ->
8014            pr "  rv = caml_copy_int64 (r);\n"
8015        | RBool _ -> pr "  rv = Val_bool (r);\n"
8016        | RConstString _ ->
8017            pr "  rv = caml_copy_string (r);\n"
8018        | RConstOptString _ ->
8019            pr "  if (r) { /* Some string */\n";
8020            pr "    v = caml_alloc (1, 0);\n";
8021            pr "    v2 = caml_copy_string (r);\n";
8022            pr "    Store_field (v, 0, v2);\n";
8023            pr "  } else /* None */\n";
8024            pr "    v = Val_int (0);\n";
8025        | RString _ ->
8026            pr "  rv = caml_copy_string (r);\n";
8027            pr "  free (r);\n"
8028        | RStringList _ ->
8029            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8030            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8031            pr "  free (r);\n"
8032        | RStruct (_, typ) ->
8033            pr "  rv = copy_%s (r);\n" typ;
8034            pr "  guestfs_free_%s (r);\n" typ;
8035        | RStructList (_, typ) ->
8036            pr "  rv = copy_%s_list (r);\n" typ;
8037            pr "  guestfs_free_%s_list (r);\n" typ;
8038        | RHashtable _ ->
8039            pr "  rv = copy_table (r);\n";
8040            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8041            pr "  free (r);\n";
8042        | RBufferOut _ ->
8043            pr "  rv = caml_alloc_string (size);\n";
8044            pr "  memcpy (String_val (rv), r, size);\n";
8045       );
8046
8047       pr "  CAMLreturn (rv);\n";
8048       pr "}\n";
8049       pr "\n";
8050
8051       if List.length params > 5 then (
8052         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8053         pr "CAMLprim value ";
8054         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8055         pr "CAMLprim value\n";
8056         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8057         pr "{\n";
8058         pr "  return ocaml_guestfs_%s (argv[0]" name;
8059         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8060         pr ");\n";
8061         pr "}\n";
8062         pr "\n"
8063       )
8064   ) all_functions_sorted
8065
8066 and generate_ocaml_structure_decls () =
8067   List.iter (
8068     fun (typ, cols) ->
8069       pr "type %s = {\n" typ;
8070       List.iter (
8071         function
8072         | name, FString -> pr "  %s : string;\n" name
8073         | name, FBuffer -> pr "  %s : string;\n" name
8074         | name, FUUID -> pr "  %s : string;\n" name
8075         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8076         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8077         | name, FChar -> pr "  %s : char;\n" name
8078         | name, FOptPercent -> pr "  %s : float option;\n" name
8079       ) cols;
8080       pr "}\n";
8081       pr "\n"
8082   ) structs
8083
8084 and generate_ocaml_prototype ?(is_external = false) name style =
8085   if is_external then pr "external " else pr "val ";
8086   pr "%s : t -> " name;
8087   List.iter (
8088     function
8089     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8090     | OptString _ -> pr "string option -> "
8091     | StringList _ | DeviceList _ -> pr "string array -> "
8092     | Bool _ -> pr "bool -> "
8093     | Int _ -> pr "int -> "
8094     | Int64 _ -> pr "int64 -> "
8095   ) (snd style);
8096   (match fst style with
8097    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8098    | RInt _ -> pr "int"
8099    | RInt64 _ -> pr "int64"
8100    | RBool _ -> pr "bool"
8101    | RConstString _ -> pr "string"
8102    | RConstOptString _ -> pr "string option"
8103    | RString _ | RBufferOut _ -> pr "string"
8104    | RStringList _ -> pr "string array"
8105    | RStruct (_, typ) -> pr "%s" typ
8106    | RStructList (_, typ) -> pr "%s array" typ
8107    | RHashtable _ -> pr "(string * string) list"
8108   );
8109   if is_external then (
8110     pr " = ";
8111     if List.length (snd style) + 1 > 5 then
8112       pr "\"ocaml_guestfs_%s_byte\" " name;
8113     pr "\"ocaml_guestfs_%s\"" name
8114   );
8115   pr "\n"
8116
8117 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8118 and generate_perl_xs () =
8119   generate_header CStyle LGPLv2plus;
8120
8121   pr "\
8122 #include \"EXTERN.h\"
8123 #include \"perl.h\"
8124 #include \"XSUB.h\"
8125
8126 #include <guestfs.h>
8127
8128 #ifndef PRId64
8129 #define PRId64 \"lld\"
8130 #endif
8131
8132 static SV *
8133 my_newSVll(long long val) {
8134 #ifdef USE_64_BIT_ALL
8135   return newSViv(val);
8136 #else
8137   char buf[100];
8138   int len;
8139   len = snprintf(buf, 100, \"%%\" PRId64, val);
8140   return newSVpv(buf, len);
8141 #endif
8142 }
8143
8144 #ifndef PRIu64
8145 #define PRIu64 \"llu\"
8146 #endif
8147
8148 static SV *
8149 my_newSVull(unsigned long long val) {
8150 #ifdef USE_64_BIT_ALL
8151   return newSVuv(val);
8152 #else
8153   char buf[100];
8154   int len;
8155   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8156   return newSVpv(buf, len);
8157 #endif
8158 }
8159
8160 /* http://www.perlmonks.org/?node_id=680842 */
8161 static char **
8162 XS_unpack_charPtrPtr (SV *arg) {
8163   char **ret;
8164   AV *av;
8165   I32 i;
8166
8167   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8168     croak (\"array reference expected\");
8169
8170   av = (AV *)SvRV (arg);
8171   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8172   if (!ret)
8173     croak (\"malloc failed\");
8174
8175   for (i = 0; i <= av_len (av); i++) {
8176     SV **elem = av_fetch (av, i, 0);
8177
8178     if (!elem || !*elem)
8179       croak (\"missing element in list\");
8180
8181     ret[i] = SvPV_nolen (*elem);
8182   }
8183
8184   ret[i] = NULL;
8185
8186   return ret;
8187 }
8188
8189 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8190
8191 PROTOTYPES: ENABLE
8192
8193 guestfs_h *
8194 _create ()
8195    CODE:
8196       RETVAL = guestfs_create ();
8197       if (!RETVAL)
8198         croak (\"could not create guestfs handle\");
8199       guestfs_set_error_handler (RETVAL, NULL, NULL);
8200  OUTPUT:
8201       RETVAL
8202
8203 void
8204 DESTROY (g)
8205       guestfs_h *g;
8206  PPCODE:
8207       guestfs_close (g);
8208
8209 ";
8210
8211   List.iter (
8212     fun (name, style, _, _, _, _, _) ->
8213       (match fst style with
8214        | RErr -> pr "void\n"
8215        | RInt _ -> pr "SV *\n"
8216        | RInt64 _ -> pr "SV *\n"
8217        | RBool _ -> pr "SV *\n"
8218        | RConstString _ -> pr "SV *\n"
8219        | RConstOptString _ -> pr "SV *\n"
8220        | RString _ -> pr "SV *\n"
8221        | RBufferOut _ -> pr "SV *\n"
8222        | RStringList _
8223        | RStruct _ | RStructList _
8224        | RHashtable _ ->
8225            pr "void\n" (* all lists returned implictly on the stack *)
8226       );
8227       (* Call and arguments. *)
8228       pr "%s " name;
8229       generate_c_call_args ~handle:"g" ~decl:true style;
8230       pr "\n";
8231       pr "      guestfs_h *g;\n";
8232       iteri (
8233         fun i ->
8234           function
8235           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8236               pr "      char *%s;\n" n
8237           | OptString n ->
8238               (* http://www.perlmonks.org/?node_id=554277
8239                * Note that the implicit handle argument means we have
8240                * to add 1 to the ST(x) operator.
8241                *)
8242               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8243           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8244           | Bool n -> pr "      int %s;\n" n
8245           | Int n -> pr "      int %s;\n" n
8246           | Int64 n -> pr "      int64_t %s;\n" n
8247       ) (snd style);
8248
8249       let do_cleanups () =
8250         List.iter (
8251           function
8252           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8253           | Bool _ | Int _ | Int64 _
8254           | FileIn _ | FileOut _ -> ()
8255           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8256         ) (snd style)
8257       in
8258
8259       (* Code. *)
8260       (match fst style with
8261        | RErr ->
8262            pr "PREINIT:\n";
8263            pr "      int r;\n";
8264            pr " PPCODE:\n";
8265            pr "      r = guestfs_%s " name;
8266            generate_c_call_args ~handle:"g" style;
8267            pr ";\n";
8268            do_cleanups ();
8269            pr "      if (r == -1)\n";
8270            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8271        | RInt n
8272        | RBool n ->
8273            pr "PREINIT:\n";
8274            pr "      int %s;\n" n;
8275            pr "   CODE:\n";
8276            pr "      %s = guestfs_%s " n name;
8277            generate_c_call_args ~handle:"g" style;
8278            pr ";\n";
8279            do_cleanups ();
8280            pr "      if (%s == -1)\n" n;
8281            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8282            pr "      RETVAL = newSViv (%s);\n" n;
8283            pr " OUTPUT:\n";
8284            pr "      RETVAL\n"
8285        | RInt64 n ->
8286            pr "PREINIT:\n";
8287            pr "      int64_t %s;\n" n;
8288            pr "   CODE:\n";
8289            pr "      %s = guestfs_%s " n name;
8290            generate_c_call_args ~handle:"g" style;
8291            pr ";\n";
8292            do_cleanups ();
8293            pr "      if (%s == -1)\n" n;
8294            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8295            pr "      RETVAL = my_newSVll (%s);\n" n;
8296            pr " OUTPUT:\n";
8297            pr "      RETVAL\n"
8298        | RConstString n ->
8299            pr "PREINIT:\n";
8300            pr "      const char *%s;\n" n;
8301            pr "   CODE:\n";
8302            pr "      %s = guestfs_%s " n name;
8303            generate_c_call_args ~handle:"g" style;
8304            pr ";\n";
8305            do_cleanups ();
8306            pr "      if (%s == NULL)\n" n;
8307            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8308            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8309            pr " OUTPUT:\n";
8310            pr "      RETVAL\n"
8311        | RConstOptString n ->
8312            pr "PREINIT:\n";
8313            pr "      const char *%s;\n" n;
8314            pr "   CODE:\n";
8315            pr "      %s = guestfs_%s " n name;
8316            generate_c_call_args ~handle:"g" style;
8317            pr ";\n";
8318            do_cleanups ();
8319            pr "      if (%s == NULL)\n" n;
8320            pr "        RETVAL = &PL_sv_undef;\n";
8321            pr "      else\n";
8322            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8323            pr " OUTPUT:\n";
8324            pr "      RETVAL\n"
8325        | RString n ->
8326            pr "PREINIT:\n";
8327            pr "      char *%s;\n" n;
8328            pr "   CODE:\n";
8329            pr "      %s = guestfs_%s " n name;
8330            generate_c_call_args ~handle:"g" style;
8331            pr ";\n";
8332            do_cleanups ();
8333            pr "      if (%s == NULL)\n" n;
8334            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8335            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8336            pr "      free (%s);\n" n;
8337            pr " OUTPUT:\n";
8338            pr "      RETVAL\n"
8339        | RStringList n | RHashtable n ->
8340            pr "PREINIT:\n";
8341            pr "      char **%s;\n" n;
8342            pr "      int i, n;\n";
8343            pr " PPCODE:\n";
8344            pr "      %s = guestfs_%s " n name;
8345            generate_c_call_args ~handle:"g" style;
8346            pr ";\n";
8347            do_cleanups ();
8348            pr "      if (%s == NULL)\n" n;
8349            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8350            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8351            pr "      EXTEND (SP, n);\n";
8352            pr "      for (i = 0; i < n; ++i) {\n";
8353            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8354            pr "        free (%s[i]);\n" n;
8355            pr "      }\n";
8356            pr "      free (%s);\n" n;
8357        | RStruct (n, typ) ->
8358            let cols = cols_of_struct typ in
8359            generate_perl_struct_code typ cols name style n do_cleanups
8360        | RStructList (n, typ) ->
8361            let cols = cols_of_struct typ in
8362            generate_perl_struct_list_code typ cols name style n do_cleanups
8363        | RBufferOut n ->
8364            pr "PREINIT:\n";
8365            pr "      char *%s;\n" n;
8366            pr "      size_t size;\n";
8367            pr "   CODE:\n";
8368            pr "      %s = guestfs_%s " n name;
8369            generate_c_call_args ~handle:"g" style;
8370            pr ";\n";
8371            do_cleanups ();
8372            pr "      if (%s == NULL)\n" n;
8373            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8374            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8375            pr "      free (%s);\n" n;
8376            pr " OUTPUT:\n";
8377            pr "      RETVAL\n"
8378       );
8379
8380       pr "\n"
8381   ) all_functions
8382
8383 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8384   pr "PREINIT:\n";
8385   pr "      struct guestfs_%s_list *%s;\n" typ n;
8386   pr "      int i;\n";
8387   pr "      HV *hv;\n";
8388   pr " PPCODE:\n";
8389   pr "      %s = guestfs_%s " n name;
8390   generate_c_call_args ~handle:"g" style;
8391   pr ";\n";
8392   do_cleanups ();
8393   pr "      if (%s == NULL)\n" n;
8394   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8395   pr "      EXTEND (SP, %s->len);\n" n;
8396   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8397   pr "        hv = newHV ();\n";
8398   List.iter (
8399     function
8400     | name, FString ->
8401         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8402           name (String.length name) n name
8403     | name, FUUID ->
8404         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8405           name (String.length name) n name
8406     | name, FBuffer ->
8407         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8408           name (String.length name) n name n name
8409     | name, (FBytes|FUInt64) ->
8410         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8411           name (String.length name) n name
8412     | name, FInt64 ->
8413         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8414           name (String.length name) n name
8415     | name, (FInt32|FUInt32) ->
8416         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8417           name (String.length name) n name
8418     | name, FChar ->
8419         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8420           name (String.length name) n name
8421     | name, FOptPercent ->
8422         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8423           name (String.length name) n name
8424   ) cols;
8425   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8426   pr "      }\n";
8427   pr "      guestfs_free_%s_list (%s);\n" typ n
8428
8429 and generate_perl_struct_code typ cols name style n do_cleanups =
8430   pr "PREINIT:\n";
8431   pr "      struct guestfs_%s *%s;\n" typ n;
8432   pr " PPCODE:\n";
8433   pr "      %s = guestfs_%s " n name;
8434   generate_c_call_args ~handle:"g" style;
8435   pr ";\n";
8436   do_cleanups ();
8437   pr "      if (%s == NULL)\n" n;
8438   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8439   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8440   List.iter (
8441     fun ((name, _) as col) ->
8442       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8443
8444       match col with
8445       | name, FString ->
8446           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8447             n name
8448       | name, FBuffer ->
8449           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8450             n name n name
8451       | name, FUUID ->
8452           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8453             n name
8454       | name, (FBytes|FUInt64) ->
8455           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8456             n name
8457       | name, FInt64 ->
8458           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8459             n name
8460       | name, (FInt32|FUInt32) ->
8461           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8462             n name
8463       | name, FChar ->
8464           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8465             n name
8466       | name, FOptPercent ->
8467           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8468             n name
8469   ) cols;
8470   pr "      free (%s);\n" n
8471
8472 (* Generate Sys/Guestfs.pm. *)
8473 and generate_perl_pm () =
8474   generate_header HashStyle LGPLv2plus;
8475
8476   pr "\
8477 =pod
8478
8479 =head1 NAME
8480
8481 Sys::Guestfs - Perl bindings for libguestfs
8482
8483 =head1 SYNOPSIS
8484
8485  use Sys::Guestfs;
8486
8487  my $h = Sys::Guestfs->new ();
8488  $h->add_drive ('guest.img');
8489  $h->launch ();
8490  $h->mount ('/dev/sda1', '/');
8491  $h->touch ('/hello');
8492  $h->sync ();
8493
8494 =head1 DESCRIPTION
8495
8496 The C<Sys::Guestfs> module provides a Perl XS binding to the
8497 libguestfs API for examining and modifying virtual machine
8498 disk images.
8499
8500 Amongst the things this is good for: making batch configuration
8501 changes to guests, getting disk used/free statistics (see also:
8502 virt-df), migrating between virtualization systems (see also:
8503 virt-p2v), performing partial backups, performing partial guest
8504 clones, cloning guests and changing registry/UUID/hostname info, and
8505 much else besides.
8506
8507 Libguestfs uses Linux kernel and qemu code, and can access any type of
8508 guest filesystem that Linux and qemu can, including but not limited
8509 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8510 schemes, qcow, qcow2, vmdk.
8511
8512 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8513 LVs, what filesystem is in each LV, etc.).  It can also run commands
8514 in the context of the guest.  Also you can access filesystems over
8515 FUSE.
8516
8517 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8518 functions for using libguestfs from Perl, including integration
8519 with libvirt.
8520
8521 =head1 ERRORS
8522
8523 All errors turn into calls to C<croak> (see L<Carp(3)>).
8524
8525 =head1 METHODS
8526
8527 =over 4
8528
8529 =cut
8530
8531 package Sys::Guestfs;
8532
8533 use strict;
8534 use warnings;
8535
8536 require XSLoader;
8537 XSLoader::load ('Sys::Guestfs');
8538
8539 =item $h = Sys::Guestfs->new ();
8540
8541 Create a new guestfs handle.
8542
8543 =cut
8544
8545 sub new {
8546   my $proto = shift;
8547   my $class = ref ($proto) || $proto;
8548
8549   my $self = Sys::Guestfs::_create ();
8550   bless $self, $class;
8551   return $self;
8552 }
8553
8554 ";
8555
8556   (* Actions.  We only need to print documentation for these as
8557    * they are pulled in from the XS code automatically.
8558    *)
8559   List.iter (
8560     fun (name, style, _, flags, _, _, longdesc) ->
8561       if not (List.mem NotInDocs flags) then (
8562         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8563         pr "=item ";
8564         generate_perl_prototype name style;
8565         pr "\n\n";
8566         pr "%s\n\n" longdesc;
8567         if List.mem ProtocolLimitWarning flags then
8568           pr "%s\n\n" protocol_limit_warning;
8569         if List.mem DangerWillRobinson flags then
8570           pr "%s\n\n" danger_will_robinson;
8571         match deprecation_notice flags with
8572         | None -> ()
8573         | Some txt -> pr "%s\n\n" txt
8574       )
8575   ) all_functions_sorted;
8576
8577   (* End of file. *)
8578   pr "\
8579 =cut
8580
8581 1;
8582
8583 =back
8584
8585 =head1 COPYRIGHT
8586
8587 Copyright (C) %s Red Hat Inc.
8588
8589 =head1 LICENSE
8590
8591 Please see the file COPYING.LIB for the full license.
8592
8593 =head1 SEE ALSO
8594
8595 L<guestfs(3)>,
8596 L<guestfish(1)>,
8597 L<http://libguestfs.org>,
8598 L<Sys::Guestfs::Lib(3)>.
8599
8600 =cut
8601 " copyright_years
8602
8603 and generate_perl_prototype name style =
8604   (match fst style with
8605    | RErr -> ()
8606    | RBool n
8607    | RInt n
8608    | RInt64 n
8609    | RConstString n
8610    | RConstOptString n
8611    | RString n
8612    | RBufferOut n -> pr "$%s = " n
8613    | RStruct (n,_)
8614    | RHashtable n -> pr "%%%s = " n
8615    | RStringList n
8616    | RStructList (n,_) -> pr "@%s = " n
8617   );
8618   pr "$h->%s (" name;
8619   let comma = ref false in
8620   List.iter (
8621     fun arg ->
8622       if !comma then pr ", ";
8623       comma := true;
8624       match arg with
8625       | Pathname n | Device n | Dev_or_Path n | String n
8626       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8627           pr "$%s" n
8628       | StringList n | DeviceList n ->
8629           pr "\\@%s" n
8630   ) (snd style);
8631   pr ");"
8632
8633 (* Generate Python C module. *)
8634 and generate_python_c () =
8635   generate_header CStyle LGPLv2plus;
8636
8637   pr "\
8638 #include <Python.h>
8639
8640 #include <stdio.h>
8641 #include <stdlib.h>
8642 #include <assert.h>
8643
8644 #include \"guestfs.h\"
8645
8646 typedef struct {
8647   PyObject_HEAD
8648   guestfs_h *g;
8649 } Pyguestfs_Object;
8650
8651 static guestfs_h *
8652 get_handle (PyObject *obj)
8653 {
8654   assert (obj);
8655   assert (obj != Py_None);
8656   return ((Pyguestfs_Object *) obj)->g;
8657 }
8658
8659 static PyObject *
8660 put_handle (guestfs_h *g)
8661 {
8662   assert (g);
8663   return
8664     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8665 }
8666
8667 /* This list should be freed (but not the strings) after use. */
8668 static char **
8669 get_string_list (PyObject *obj)
8670 {
8671   int i, len;
8672   char **r;
8673
8674   assert (obj);
8675
8676   if (!PyList_Check (obj)) {
8677     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8678     return NULL;
8679   }
8680
8681   len = PyList_Size (obj);
8682   r = malloc (sizeof (char *) * (len+1));
8683   if (r == NULL) {
8684     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8685     return NULL;
8686   }
8687
8688   for (i = 0; i < len; ++i)
8689     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8690   r[len] = NULL;
8691
8692   return r;
8693 }
8694
8695 static PyObject *
8696 put_string_list (char * const * const argv)
8697 {
8698   PyObject *list;
8699   int argc, i;
8700
8701   for (argc = 0; argv[argc] != NULL; ++argc)
8702     ;
8703
8704   list = PyList_New (argc);
8705   for (i = 0; i < argc; ++i)
8706     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8707
8708   return list;
8709 }
8710
8711 static PyObject *
8712 put_table (char * const * const argv)
8713 {
8714   PyObject *list, *item;
8715   int argc, i;
8716
8717   for (argc = 0; argv[argc] != NULL; ++argc)
8718     ;
8719
8720   list = PyList_New (argc >> 1);
8721   for (i = 0; i < argc; i += 2) {
8722     item = PyTuple_New (2);
8723     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8724     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8725     PyList_SetItem (list, i >> 1, item);
8726   }
8727
8728   return list;
8729 }
8730
8731 static void
8732 free_strings (char **argv)
8733 {
8734   int argc;
8735
8736   for (argc = 0; argv[argc] != NULL; ++argc)
8737     free (argv[argc]);
8738   free (argv);
8739 }
8740
8741 static PyObject *
8742 py_guestfs_create (PyObject *self, PyObject *args)
8743 {
8744   guestfs_h *g;
8745
8746   g = guestfs_create ();
8747   if (g == NULL) {
8748     PyErr_SetString (PyExc_RuntimeError,
8749                      \"guestfs.create: failed to allocate handle\");
8750     return NULL;
8751   }
8752   guestfs_set_error_handler (g, NULL, NULL);
8753   return put_handle (g);
8754 }
8755
8756 static PyObject *
8757 py_guestfs_close (PyObject *self, PyObject *args)
8758 {
8759   PyObject *py_g;
8760   guestfs_h *g;
8761
8762   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8763     return NULL;
8764   g = get_handle (py_g);
8765
8766   guestfs_close (g);
8767
8768   Py_INCREF (Py_None);
8769   return Py_None;
8770 }
8771
8772 ";
8773
8774   let emit_put_list_function typ =
8775     pr "static PyObject *\n";
8776     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8777     pr "{\n";
8778     pr "  PyObject *list;\n";
8779     pr "  int i;\n";
8780     pr "\n";
8781     pr "  list = PyList_New (%ss->len);\n" typ;
8782     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8783     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8784     pr "  return list;\n";
8785     pr "};\n";
8786     pr "\n"
8787   in
8788
8789   (* Structures, turned into Python dictionaries. *)
8790   List.iter (
8791     fun (typ, cols) ->
8792       pr "static PyObject *\n";
8793       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8794       pr "{\n";
8795       pr "  PyObject *dict;\n";
8796       pr "\n";
8797       pr "  dict = PyDict_New ();\n";
8798       List.iter (
8799         function
8800         | name, FString ->
8801             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8802             pr "                        PyString_FromString (%s->%s));\n"
8803               typ name
8804         | name, FBuffer ->
8805             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8806             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8807               typ name typ name
8808         | name, FUUID ->
8809             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8810             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8811               typ name
8812         | name, (FBytes|FUInt64) ->
8813             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8814             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8815               typ name
8816         | name, FInt64 ->
8817             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8818             pr "                        PyLong_FromLongLong (%s->%s));\n"
8819               typ name
8820         | name, FUInt32 ->
8821             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8822             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8823               typ name
8824         | name, FInt32 ->
8825             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8826             pr "                        PyLong_FromLong (%s->%s));\n"
8827               typ name
8828         | name, FOptPercent ->
8829             pr "  if (%s->%s >= 0)\n" typ name;
8830             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8831             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8832               typ name;
8833             pr "  else {\n";
8834             pr "    Py_INCREF (Py_None);\n";
8835             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8836             pr "  }\n"
8837         | name, FChar ->
8838             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8839             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8840       ) cols;
8841       pr "  return dict;\n";
8842       pr "};\n";
8843       pr "\n";
8844
8845   ) structs;
8846
8847   (* Emit a put_TYPE_list function definition only if that function is used. *)
8848   List.iter (
8849     function
8850     | typ, (RStructListOnly | RStructAndList) ->
8851         (* generate the function for typ *)
8852         emit_put_list_function typ
8853     | typ, _ -> () (* empty *)
8854   ) (rstructs_used_by all_functions);
8855
8856   (* Python wrapper functions. *)
8857   List.iter (
8858     fun (name, style, _, _, _, _, _) ->
8859       pr "static PyObject *\n";
8860       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8861       pr "{\n";
8862
8863       pr "  PyObject *py_g;\n";
8864       pr "  guestfs_h *g;\n";
8865       pr "  PyObject *py_r;\n";
8866
8867       let error_code =
8868         match fst style with
8869         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8870         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8871         | RConstString _ | RConstOptString _ ->
8872             pr "  const char *r;\n"; "NULL"
8873         | RString _ -> pr "  char *r;\n"; "NULL"
8874         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8875         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8876         | RStructList (_, typ) ->
8877             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8878         | RBufferOut _ ->
8879             pr "  char *r;\n";
8880             pr "  size_t size;\n";
8881             "NULL" in
8882
8883       List.iter (
8884         function
8885         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8886             pr "  const char *%s;\n" n
8887         | OptString n -> pr "  const char *%s;\n" n
8888         | StringList n | DeviceList n ->
8889             pr "  PyObject *py_%s;\n" n;
8890             pr "  char **%s;\n" n
8891         | Bool n -> pr "  int %s;\n" n
8892         | Int n -> pr "  int %s;\n" n
8893         | Int64 n -> pr "  long long %s;\n" n
8894       ) (snd style);
8895
8896       pr "\n";
8897
8898       (* Convert the parameters. *)
8899       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8900       List.iter (
8901         function
8902         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8903         | OptString _ -> pr "z"
8904         | StringList _ | DeviceList _ -> pr "O"
8905         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8906         | Int _ -> pr "i"
8907         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8908                              * emulate C's int/long/long long in Python?
8909                              *)
8910       ) (snd style);
8911       pr ":guestfs_%s\",\n" name;
8912       pr "                         &py_g";
8913       List.iter (
8914         function
8915         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8916         | OptString n -> pr ", &%s" n
8917         | StringList n | DeviceList n -> pr ", &py_%s" n
8918         | Bool n -> pr ", &%s" n
8919         | Int n -> pr ", &%s" n
8920         | Int64 n -> pr ", &%s" n
8921       ) (snd style);
8922
8923       pr "))\n";
8924       pr "    return NULL;\n";
8925
8926       pr "  g = get_handle (py_g);\n";
8927       List.iter (
8928         function
8929         | Pathname _ | Device _ | Dev_or_Path _ | String _
8930         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8931         | StringList n | DeviceList n ->
8932             pr "  %s = get_string_list (py_%s);\n" n n;
8933             pr "  if (!%s) return NULL;\n" n
8934       ) (snd style);
8935
8936       pr "\n";
8937
8938       pr "  r = guestfs_%s " name;
8939       generate_c_call_args ~handle:"g" style;
8940       pr ";\n";
8941
8942       List.iter (
8943         function
8944         | Pathname _ | Device _ | Dev_or_Path _ | String _
8945         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8946         | StringList n | DeviceList n ->
8947             pr "  free (%s);\n" n
8948       ) (snd style);
8949
8950       pr "  if (r == %s) {\n" error_code;
8951       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8952       pr "    return NULL;\n";
8953       pr "  }\n";
8954       pr "\n";
8955
8956       (match fst style with
8957        | RErr ->
8958            pr "  Py_INCREF (Py_None);\n";
8959            pr "  py_r = Py_None;\n"
8960        | RInt _
8961        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8962        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8963        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8964        | RConstOptString _ ->
8965            pr "  if (r)\n";
8966            pr "    py_r = PyString_FromString (r);\n";
8967            pr "  else {\n";
8968            pr "    Py_INCREF (Py_None);\n";
8969            pr "    py_r = Py_None;\n";
8970            pr "  }\n"
8971        | RString _ ->
8972            pr "  py_r = PyString_FromString (r);\n";
8973            pr "  free (r);\n"
8974        | RStringList _ ->
8975            pr "  py_r = put_string_list (r);\n";
8976            pr "  free_strings (r);\n"
8977        | RStruct (_, typ) ->
8978            pr "  py_r = put_%s (r);\n" typ;
8979            pr "  guestfs_free_%s (r);\n" typ
8980        | RStructList (_, typ) ->
8981            pr "  py_r = put_%s_list (r);\n" typ;
8982            pr "  guestfs_free_%s_list (r);\n" typ
8983        | RHashtable n ->
8984            pr "  py_r = put_table (r);\n";
8985            pr "  free_strings (r);\n"
8986        | RBufferOut _ ->
8987            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8988            pr "  free (r);\n"
8989       );
8990
8991       pr "  return py_r;\n";
8992       pr "}\n";
8993       pr "\n"
8994   ) all_functions;
8995
8996   (* Table of functions. *)
8997   pr "static PyMethodDef methods[] = {\n";
8998   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8999   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9000   List.iter (
9001     fun (name, _, _, _, _, _, _) ->
9002       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9003         name name
9004   ) all_functions;
9005   pr "  { NULL, NULL, 0, NULL }\n";
9006   pr "};\n";
9007   pr "\n";
9008
9009   (* Init function. *)
9010   pr "\
9011 void
9012 initlibguestfsmod (void)
9013 {
9014   static int initialized = 0;
9015
9016   if (initialized) return;
9017   Py_InitModule ((char *) \"libguestfsmod\", methods);
9018   initialized = 1;
9019 }
9020 "
9021
9022 (* Generate Python module. *)
9023 and generate_python_py () =
9024   generate_header HashStyle LGPLv2plus;
9025
9026   pr "\
9027 u\"\"\"Python bindings for libguestfs
9028
9029 import guestfs
9030 g = guestfs.GuestFS ()
9031 g.add_drive (\"guest.img\")
9032 g.launch ()
9033 parts = g.list_partitions ()
9034
9035 The guestfs module provides a Python binding to the libguestfs API
9036 for examining and modifying virtual machine disk images.
9037
9038 Amongst the things this is good for: making batch configuration
9039 changes to guests, getting disk used/free statistics (see also:
9040 virt-df), migrating between virtualization systems (see also:
9041 virt-p2v), performing partial backups, performing partial guest
9042 clones, cloning guests and changing registry/UUID/hostname info, and
9043 much else besides.
9044
9045 Libguestfs uses Linux kernel and qemu code, and can access any type of
9046 guest filesystem that Linux and qemu can, including but not limited
9047 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9048 schemes, qcow, qcow2, vmdk.
9049
9050 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9051 LVs, what filesystem is in each LV, etc.).  It can also run commands
9052 in the context of the guest.  Also you can access filesystems over
9053 FUSE.
9054
9055 Errors which happen while using the API are turned into Python
9056 RuntimeError exceptions.
9057
9058 To create a guestfs handle you usually have to perform the following
9059 sequence of calls:
9060
9061 # Create the handle, call add_drive at least once, and possibly
9062 # several times if the guest has multiple block devices:
9063 g = guestfs.GuestFS ()
9064 g.add_drive (\"guest.img\")
9065
9066 # Launch the qemu subprocess and wait for it to become ready:
9067 g.launch ()
9068
9069 # Now you can issue commands, for example:
9070 logvols = g.lvs ()
9071
9072 \"\"\"
9073
9074 import libguestfsmod
9075
9076 class GuestFS:
9077     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9078
9079     def __init__ (self):
9080         \"\"\"Create a new libguestfs handle.\"\"\"
9081         self._o = libguestfsmod.create ()
9082
9083     def __del__ (self):
9084         libguestfsmod.close (self._o)
9085
9086 ";
9087
9088   List.iter (
9089     fun (name, style, _, flags, _, _, longdesc) ->
9090       pr "    def %s " name;
9091       generate_py_call_args ~handle:"self" (snd style);
9092       pr ":\n";
9093
9094       if not (List.mem NotInDocs flags) then (
9095         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9096         let doc =
9097           match fst style with
9098           | RErr | RInt _ | RInt64 _ | RBool _
9099           | RConstOptString _ | RConstString _
9100           | RString _ | RBufferOut _ -> doc
9101           | RStringList _ ->
9102               doc ^ "\n\nThis function returns a list of strings."
9103           | RStruct (_, typ) ->
9104               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9105           | RStructList (_, typ) ->
9106               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9107           | RHashtable _ ->
9108               doc ^ "\n\nThis function returns a dictionary." in
9109         let doc =
9110           if List.mem ProtocolLimitWarning flags then
9111             doc ^ "\n\n" ^ protocol_limit_warning
9112           else doc in
9113         let doc =
9114           if List.mem DangerWillRobinson flags then
9115             doc ^ "\n\n" ^ danger_will_robinson
9116           else doc in
9117         let doc =
9118           match deprecation_notice flags with
9119           | None -> doc
9120           | Some txt -> doc ^ "\n\n" ^ txt in
9121         let doc = pod2text ~width:60 name doc in
9122         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9123         let doc = String.concat "\n        " doc in
9124         pr "        u\"\"\"%s\"\"\"\n" doc;
9125       );
9126       pr "        return libguestfsmod.%s " name;
9127       generate_py_call_args ~handle:"self._o" (snd style);
9128       pr "\n";
9129       pr "\n";
9130   ) all_functions
9131
9132 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9133 and generate_py_call_args ~handle args =
9134   pr "(%s" handle;
9135   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9136   pr ")"
9137
9138 (* Useful if you need the longdesc POD text as plain text.  Returns a
9139  * list of lines.
9140  *
9141  * Because this is very slow (the slowest part of autogeneration),
9142  * we memoize the results.
9143  *)
9144 and pod2text ~width name longdesc =
9145   let key = width, name, longdesc in
9146   try Hashtbl.find pod2text_memo key
9147   with Not_found ->
9148     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9149     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9150     close_out chan;
9151     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9152     let chan = open_process_in cmd in
9153     let lines = ref [] in
9154     let rec loop i =
9155       let line = input_line chan in
9156       if i = 1 then             (* discard the first line of output *)
9157         loop (i+1)
9158       else (
9159         let line = triml line in
9160         lines := line :: !lines;
9161         loop (i+1)
9162       ) in
9163     let lines = try loop 1 with End_of_file -> List.rev !lines in
9164     unlink filename;
9165     (match close_process_in chan with
9166      | WEXITED 0 -> ()
9167      | WEXITED i ->
9168          failwithf "pod2text: process exited with non-zero status (%d)" i
9169      | WSIGNALED i | WSTOPPED i ->
9170          failwithf "pod2text: process signalled or stopped by signal %d" i
9171     );
9172     Hashtbl.add pod2text_memo key lines;
9173     pod2text_memo_updated ();
9174     lines
9175
9176 (* Generate ruby bindings. *)
9177 and generate_ruby_c () =
9178   generate_header CStyle LGPLv2plus;
9179
9180   pr "\
9181 #include <stdio.h>
9182 #include <stdlib.h>
9183
9184 #include <ruby.h>
9185
9186 #include \"guestfs.h\"
9187
9188 #include \"extconf.h\"
9189
9190 /* For Ruby < 1.9 */
9191 #ifndef RARRAY_LEN
9192 #define RARRAY_LEN(r) (RARRAY((r))->len)
9193 #endif
9194
9195 static VALUE m_guestfs;                 /* guestfs module */
9196 static VALUE c_guestfs;                 /* guestfs_h handle */
9197 static VALUE e_Error;                   /* used for all errors */
9198
9199 static void ruby_guestfs_free (void *p)
9200 {
9201   if (!p) return;
9202   guestfs_close ((guestfs_h *) p);
9203 }
9204
9205 static VALUE ruby_guestfs_create (VALUE m)
9206 {
9207   guestfs_h *g;
9208
9209   g = guestfs_create ();
9210   if (!g)
9211     rb_raise (e_Error, \"failed to create guestfs handle\");
9212
9213   /* Don't print error messages to stderr by default. */
9214   guestfs_set_error_handler (g, NULL, NULL);
9215
9216   /* Wrap it, and make sure the close function is called when the
9217    * handle goes away.
9218    */
9219   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9220 }
9221
9222 static VALUE ruby_guestfs_close (VALUE gv)
9223 {
9224   guestfs_h *g;
9225   Data_Get_Struct (gv, guestfs_h, g);
9226
9227   ruby_guestfs_free (g);
9228   DATA_PTR (gv) = NULL;
9229
9230   return Qnil;
9231 }
9232
9233 ";
9234
9235   List.iter (
9236     fun (name, style, _, _, _, _, _) ->
9237       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9238       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9239       pr ")\n";
9240       pr "{\n";
9241       pr "  guestfs_h *g;\n";
9242       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9243       pr "  if (!g)\n";
9244       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9245         name;
9246       pr "\n";
9247
9248       List.iter (
9249         function
9250         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9251             pr "  Check_Type (%sv, T_STRING);\n" n;
9252             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9253             pr "  if (!%s)\n" n;
9254             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9255             pr "              \"%s\", \"%s\");\n" n name
9256         | OptString n ->
9257             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9258         | StringList n | DeviceList n ->
9259             pr "  char **%s;\n" n;
9260             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9261             pr "  {\n";
9262             pr "    int i, len;\n";
9263             pr "    len = RARRAY_LEN (%sv);\n" n;
9264             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9265               n;
9266             pr "    for (i = 0; i < len; ++i) {\n";
9267             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9268             pr "      %s[i] = StringValueCStr (v);\n" n;
9269             pr "    }\n";
9270             pr "    %s[len] = NULL;\n" n;
9271             pr "  }\n";
9272         | Bool n ->
9273             pr "  int %s = RTEST (%sv);\n" n n
9274         | Int n ->
9275             pr "  int %s = NUM2INT (%sv);\n" n n
9276         | Int64 n ->
9277             pr "  long long %s = NUM2LL (%sv);\n" n n
9278       ) (snd style);
9279       pr "\n";
9280
9281       let error_code =
9282         match fst style with
9283         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9284         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9285         | RConstString _ | RConstOptString _ ->
9286             pr "  const char *r;\n"; "NULL"
9287         | RString _ -> pr "  char *r;\n"; "NULL"
9288         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9289         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9290         | RStructList (_, typ) ->
9291             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9292         | RBufferOut _ ->
9293             pr "  char *r;\n";
9294             pr "  size_t size;\n";
9295             "NULL" in
9296       pr "\n";
9297
9298       pr "  r = guestfs_%s " name;
9299       generate_c_call_args ~handle:"g" style;
9300       pr ";\n";
9301
9302       List.iter (
9303         function
9304         | Pathname _ | Device _ | Dev_or_Path _ | String _
9305         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9306         | StringList n | DeviceList n ->
9307             pr "  free (%s);\n" n
9308       ) (snd style);
9309
9310       pr "  if (r == %s)\n" error_code;
9311       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9312       pr "\n";
9313
9314       (match fst style with
9315        | RErr ->
9316            pr "  return Qnil;\n"
9317        | RInt _ | RBool _ ->
9318            pr "  return INT2NUM (r);\n"
9319        | RInt64 _ ->
9320            pr "  return ULL2NUM (r);\n"
9321        | RConstString _ ->
9322            pr "  return rb_str_new2 (r);\n";
9323        | RConstOptString _ ->
9324            pr "  if (r)\n";
9325            pr "    return rb_str_new2 (r);\n";
9326            pr "  else\n";
9327            pr "    return Qnil;\n";
9328        | RString _ ->
9329            pr "  VALUE rv = rb_str_new2 (r);\n";
9330            pr "  free (r);\n";
9331            pr "  return rv;\n";
9332        | RStringList _ ->
9333            pr "  int i, len = 0;\n";
9334            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9335            pr "  VALUE rv = rb_ary_new2 (len);\n";
9336            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9337            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9338            pr "    free (r[i]);\n";
9339            pr "  }\n";
9340            pr "  free (r);\n";
9341            pr "  return rv;\n"
9342        | RStruct (_, typ) ->
9343            let cols = cols_of_struct typ in
9344            generate_ruby_struct_code typ cols
9345        | RStructList (_, typ) ->
9346            let cols = cols_of_struct typ in
9347            generate_ruby_struct_list_code typ cols
9348        | RHashtable _ ->
9349            pr "  VALUE rv = rb_hash_new ();\n";
9350            pr "  int i;\n";
9351            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9352            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9353            pr "    free (r[i]);\n";
9354            pr "    free (r[i+1]);\n";
9355            pr "  }\n";
9356            pr "  free (r);\n";
9357            pr "  return rv;\n"
9358        | RBufferOut _ ->
9359            pr "  VALUE rv = rb_str_new (r, size);\n";
9360            pr "  free (r);\n";
9361            pr "  return rv;\n";
9362       );
9363
9364       pr "}\n";
9365       pr "\n"
9366   ) all_functions;
9367
9368   pr "\
9369 /* Initialize the module. */
9370 void Init__guestfs ()
9371 {
9372   m_guestfs = rb_define_module (\"Guestfs\");
9373   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9374   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9375
9376   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9377   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9378
9379 ";
9380   (* Define the rest of the methods. *)
9381   List.iter (
9382     fun (name, style, _, _, _, _, _) ->
9383       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9384       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9385   ) all_functions;
9386
9387   pr "}\n"
9388
9389 (* Ruby code to return a struct. *)
9390 and generate_ruby_struct_code typ cols =
9391   pr "  VALUE rv = rb_hash_new ();\n";
9392   List.iter (
9393     function
9394     | name, FString ->
9395         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9396     | name, FBuffer ->
9397         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9398     | name, FUUID ->
9399         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9400     | name, (FBytes|FUInt64) ->
9401         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9402     | name, FInt64 ->
9403         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9404     | name, FUInt32 ->
9405         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9406     | name, FInt32 ->
9407         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9408     | name, FOptPercent ->
9409         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9410     | name, FChar -> (* XXX wrong? *)
9411         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9412   ) cols;
9413   pr "  guestfs_free_%s (r);\n" typ;
9414   pr "  return rv;\n"
9415
9416 (* Ruby code to return a struct list. *)
9417 and generate_ruby_struct_list_code typ cols =
9418   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9419   pr "  int i;\n";
9420   pr "  for (i = 0; i < r->len; ++i) {\n";
9421   pr "    VALUE hv = rb_hash_new ();\n";
9422   List.iter (
9423     function
9424     | name, FString ->
9425         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9426     | name, FBuffer ->
9427         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
9428     | name, FUUID ->
9429         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9430     | name, (FBytes|FUInt64) ->
9431         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9432     | name, FInt64 ->
9433         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9434     | name, FUInt32 ->
9435         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9436     | name, FInt32 ->
9437         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9438     | name, FOptPercent ->
9439         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9440     | name, FChar -> (* XXX wrong? *)
9441         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9442   ) cols;
9443   pr "    rb_ary_push (rv, hv);\n";
9444   pr "  }\n";
9445   pr "  guestfs_free_%s_list (r);\n" typ;
9446   pr "  return rv;\n"
9447
9448 (* Generate Java bindings GuestFS.java file. *)
9449 and generate_java_java () =
9450   generate_header CStyle LGPLv2plus;
9451
9452   pr "\
9453 package com.redhat.et.libguestfs;
9454
9455 import java.util.HashMap;
9456 import com.redhat.et.libguestfs.LibGuestFSException;
9457 import com.redhat.et.libguestfs.PV;
9458 import com.redhat.et.libguestfs.VG;
9459 import com.redhat.et.libguestfs.LV;
9460 import com.redhat.et.libguestfs.Stat;
9461 import com.redhat.et.libguestfs.StatVFS;
9462 import com.redhat.et.libguestfs.IntBool;
9463 import com.redhat.et.libguestfs.Dirent;
9464
9465 /**
9466  * The GuestFS object is a libguestfs handle.
9467  *
9468  * @author rjones
9469  */
9470 public class GuestFS {
9471   // Load the native code.
9472   static {
9473     System.loadLibrary (\"guestfs_jni\");
9474   }
9475
9476   /**
9477    * The native guestfs_h pointer.
9478    */
9479   long g;
9480
9481   /**
9482    * Create a libguestfs handle.
9483    *
9484    * @throws LibGuestFSException
9485    */
9486   public GuestFS () throws LibGuestFSException
9487   {
9488     g = _create ();
9489   }
9490   private native long _create () throws LibGuestFSException;
9491
9492   /**
9493    * Close a libguestfs handle.
9494    *
9495    * You can also leave handles to be collected by the garbage
9496    * collector, but this method ensures that the resources used
9497    * by the handle are freed up immediately.  If you call any
9498    * other methods after closing the handle, you will get an
9499    * exception.
9500    *
9501    * @throws LibGuestFSException
9502    */
9503   public void close () throws LibGuestFSException
9504   {
9505     if (g != 0)
9506       _close (g);
9507     g = 0;
9508   }
9509   private native void _close (long g) throws LibGuestFSException;
9510
9511   public void finalize () throws LibGuestFSException
9512   {
9513     close ();
9514   }
9515
9516 ";
9517
9518   List.iter (
9519     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9520       if not (List.mem NotInDocs flags); then (
9521         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9522         let doc =
9523           if List.mem ProtocolLimitWarning flags then
9524             doc ^ "\n\n" ^ protocol_limit_warning
9525           else doc in
9526         let doc =
9527           if List.mem DangerWillRobinson flags then
9528             doc ^ "\n\n" ^ danger_will_robinson
9529           else doc in
9530         let doc =
9531           match deprecation_notice flags with
9532           | None -> doc
9533           | Some txt -> doc ^ "\n\n" ^ txt in
9534         let doc = pod2text ~width:60 name doc in
9535         let doc = List.map (            (* RHBZ#501883 *)
9536           function
9537           | "" -> "<p>"
9538           | nonempty -> nonempty
9539         ) doc in
9540         let doc = String.concat "\n   * " doc in
9541
9542         pr "  /**\n";
9543         pr "   * %s\n" shortdesc;
9544         pr "   * <p>\n";
9545         pr "   * %s\n" doc;
9546         pr "   * @throws LibGuestFSException\n";
9547         pr "   */\n";
9548         pr "  ";
9549       );
9550       generate_java_prototype ~public:true ~semicolon:false name style;
9551       pr "\n";
9552       pr "  {\n";
9553       pr "    if (g == 0)\n";
9554       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9555         name;
9556       pr "    ";
9557       if fst style <> RErr then pr "return ";
9558       pr "_%s " name;
9559       generate_java_call_args ~handle:"g" (snd style);
9560       pr ";\n";
9561       pr "  }\n";
9562       pr "  ";
9563       generate_java_prototype ~privat:true ~native:true name style;
9564       pr "\n";
9565       pr "\n";
9566   ) all_functions;
9567
9568   pr "}\n"
9569
9570 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9571 and generate_java_call_args ~handle args =
9572   pr "(%s" handle;
9573   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9574   pr ")"
9575
9576 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9577     ?(semicolon=true) name style =
9578   if privat then pr "private ";
9579   if public then pr "public ";
9580   if native then pr "native ";
9581
9582   (* return type *)
9583   (match fst style with
9584    | RErr -> pr "void ";
9585    | RInt _ -> pr "int ";
9586    | RInt64 _ -> pr "long ";
9587    | RBool _ -> pr "boolean ";
9588    | RConstString _ | RConstOptString _ | RString _
9589    | RBufferOut _ -> pr "String ";
9590    | RStringList _ -> pr "String[] ";
9591    | RStruct (_, typ) ->
9592        let name = java_name_of_struct typ in
9593        pr "%s " name;
9594    | RStructList (_, typ) ->
9595        let name = java_name_of_struct typ in
9596        pr "%s[] " name;
9597    | RHashtable _ -> pr "HashMap<String,String> ";
9598   );
9599
9600   if native then pr "_%s " name else pr "%s " name;
9601   pr "(";
9602   let needs_comma = ref false in
9603   if native then (
9604     pr "long g";
9605     needs_comma := true
9606   );
9607
9608   (* args *)
9609   List.iter (
9610     fun arg ->
9611       if !needs_comma then pr ", ";
9612       needs_comma := true;
9613
9614       match arg with
9615       | Pathname n
9616       | Device n | Dev_or_Path n
9617       | String n
9618       | OptString n
9619       | FileIn n
9620       | FileOut n ->
9621           pr "String %s" n
9622       | StringList n | DeviceList n ->
9623           pr "String[] %s" n
9624       | Bool n ->
9625           pr "boolean %s" n
9626       | Int n ->
9627           pr "int %s" n
9628       | Int64 n ->
9629           pr "long %s" n
9630   ) (snd style);
9631
9632   pr ")\n";
9633   pr "    throws LibGuestFSException";
9634   if semicolon then pr ";"
9635
9636 and generate_java_struct jtyp cols () =
9637   generate_header CStyle LGPLv2plus;
9638
9639   pr "\
9640 package com.redhat.et.libguestfs;
9641
9642 /**
9643  * Libguestfs %s structure.
9644  *
9645  * @author rjones
9646  * @see GuestFS
9647  */
9648 public class %s {
9649 " jtyp jtyp;
9650
9651   List.iter (
9652     function
9653     | name, FString
9654     | name, FUUID
9655     | name, FBuffer -> pr "  public String %s;\n" name
9656     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9657     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9658     | name, FChar -> pr "  public char %s;\n" name
9659     | name, FOptPercent ->
9660         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9661         pr "  public float %s;\n" name
9662   ) cols;
9663
9664   pr "}\n"
9665
9666 and generate_java_c () =
9667   generate_header CStyle LGPLv2plus;
9668
9669   pr "\
9670 #include <stdio.h>
9671 #include <stdlib.h>
9672 #include <string.h>
9673
9674 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9675 #include \"guestfs.h\"
9676
9677 /* Note that this function returns.  The exception is not thrown
9678  * until after the wrapper function returns.
9679  */
9680 static void
9681 throw_exception (JNIEnv *env, const char *msg)
9682 {
9683   jclass cl;
9684   cl = (*env)->FindClass (env,
9685                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9686   (*env)->ThrowNew (env, cl, msg);
9687 }
9688
9689 JNIEXPORT jlong JNICALL
9690 Java_com_redhat_et_libguestfs_GuestFS__1create
9691   (JNIEnv *env, jobject obj)
9692 {
9693   guestfs_h *g;
9694
9695   g = guestfs_create ();
9696   if (g == NULL) {
9697     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9698     return 0;
9699   }
9700   guestfs_set_error_handler (g, NULL, NULL);
9701   return (jlong) (long) g;
9702 }
9703
9704 JNIEXPORT void JNICALL
9705 Java_com_redhat_et_libguestfs_GuestFS__1close
9706   (JNIEnv *env, jobject obj, jlong jg)
9707 {
9708   guestfs_h *g = (guestfs_h *) (long) jg;
9709   guestfs_close (g);
9710 }
9711
9712 ";
9713
9714   List.iter (
9715     fun (name, style, _, _, _, _, _) ->
9716       pr "JNIEXPORT ";
9717       (match fst style with
9718        | RErr -> pr "void ";
9719        | RInt _ -> pr "jint ";
9720        | RInt64 _ -> pr "jlong ";
9721        | RBool _ -> pr "jboolean ";
9722        | RConstString _ | RConstOptString _ | RString _
9723        | RBufferOut _ -> pr "jstring ";
9724        | RStruct _ | RHashtable _ ->
9725            pr "jobject ";
9726        | RStringList _ | RStructList _ ->
9727            pr "jobjectArray ";
9728       );
9729       pr "JNICALL\n";
9730       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9731       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9732       pr "\n";
9733       pr "  (JNIEnv *env, jobject obj, jlong jg";
9734       List.iter (
9735         function
9736         | Pathname n
9737         | Device n | Dev_or_Path n
9738         | String n
9739         | OptString n
9740         | FileIn n
9741         | FileOut n ->
9742             pr ", jstring j%s" n
9743         | StringList n | DeviceList n ->
9744             pr ", jobjectArray j%s" n
9745         | Bool n ->
9746             pr ", jboolean j%s" n
9747         | Int n ->
9748             pr ", jint j%s" n
9749         | Int64 n ->
9750             pr ", jlong j%s" n
9751       ) (snd style);
9752       pr ")\n";
9753       pr "{\n";
9754       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9755       let error_code, no_ret =
9756         match fst style with
9757         | RErr -> pr "  int r;\n"; "-1", ""
9758         | RBool _
9759         | RInt _ -> pr "  int r;\n"; "-1", "0"
9760         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9761         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9762         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9763         | RString _ ->
9764             pr "  jstring jr;\n";
9765             pr "  char *r;\n"; "NULL", "NULL"
9766         | RStringList _ ->
9767             pr "  jobjectArray jr;\n";
9768             pr "  int r_len;\n";
9769             pr "  jclass cl;\n";
9770             pr "  jstring jstr;\n";
9771             pr "  char **r;\n"; "NULL", "NULL"
9772         | RStruct (_, typ) ->
9773             pr "  jobject jr;\n";
9774             pr "  jclass cl;\n";
9775             pr "  jfieldID fl;\n";
9776             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9777         | RStructList (_, typ) ->
9778             pr "  jobjectArray jr;\n";
9779             pr "  jclass cl;\n";
9780             pr "  jfieldID fl;\n";
9781             pr "  jobject jfl;\n";
9782             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9783         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9784         | RBufferOut _ ->
9785             pr "  jstring jr;\n";
9786             pr "  char *r;\n";
9787             pr "  size_t size;\n";
9788             "NULL", "NULL" in
9789       List.iter (
9790         function
9791         | Pathname n
9792         | Device n | Dev_or_Path n
9793         | String n
9794         | OptString n
9795         | FileIn n
9796         | FileOut n ->
9797             pr "  const char *%s;\n" n
9798         | StringList n | DeviceList n ->
9799             pr "  int %s_len;\n" n;
9800             pr "  const char **%s;\n" n
9801         | Bool n
9802         | Int n ->
9803             pr "  int %s;\n" n
9804         | Int64 n ->
9805             pr "  int64_t %s;\n" n
9806       ) (snd style);
9807
9808       let needs_i =
9809         (match fst style with
9810          | RStringList _ | RStructList _ -> true
9811          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9812          | RConstOptString _
9813          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9814           List.exists (function
9815                        | StringList _ -> true
9816                        | DeviceList _ -> true
9817                        | _ -> false) (snd style) in
9818       if needs_i then
9819         pr "  int i;\n";
9820
9821       pr "\n";
9822
9823       (* Get the parameters. *)
9824       List.iter (
9825         function
9826         | Pathname n
9827         | Device n | Dev_or_Path n
9828         | String n
9829         | FileIn n
9830         | FileOut n ->
9831             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9832         | OptString n ->
9833             (* This is completely undocumented, but Java null becomes
9834              * a NULL parameter.
9835              *)
9836             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9837         | StringList n | DeviceList n ->
9838             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9839             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9840             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9841             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9842               n;
9843             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9844             pr "  }\n";
9845             pr "  %s[%s_len] = NULL;\n" n n;
9846         | Bool n
9847         | Int n
9848         | Int64 n ->
9849             pr "  %s = j%s;\n" n n
9850       ) (snd style);
9851
9852       (* Make the call. *)
9853       pr "  r = guestfs_%s " name;
9854       generate_c_call_args ~handle:"g" style;
9855       pr ";\n";
9856
9857       (* Release the parameters. *)
9858       List.iter (
9859         function
9860         | Pathname n
9861         | Device n | Dev_or_Path n
9862         | String n
9863         | FileIn n
9864         | FileOut n ->
9865             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9866         | OptString n ->
9867             pr "  if (j%s)\n" n;
9868             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9869         | StringList n | DeviceList n ->
9870             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9871             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9872               n;
9873             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9874             pr "  }\n";
9875             pr "  free (%s);\n" n
9876         | Bool n
9877         | Int n
9878         | Int64 n -> ()
9879       ) (snd style);
9880
9881       (* Check for errors. *)
9882       pr "  if (r == %s) {\n" error_code;
9883       pr "    throw_exception (env, guestfs_last_error (g));\n";
9884       pr "    return %s;\n" no_ret;
9885       pr "  }\n";
9886
9887       (* Return value. *)
9888       (match fst style with
9889        | RErr -> ()
9890        | RInt _ -> pr "  return (jint) r;\n"
9891        | RBool _ -> pr "  return (jboolean) r;\n"
9892        | RInt64 _ -> pr "  return (jlong) r;\n"
9893        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9894        | RConstOptString _ ->
9895            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9896        | RString _ ->
9897            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9898            pr "  free (r);\n";
9899            pr "  return jr;\n"
9900        | RStringList _ ->
9901            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9902            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9903            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9904            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9905            pr "  for (i = 0; i < r_len; ++i) {\n";
9906            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9907            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9908            pr "    free (r[i]);\n";
9909            pr "  }\n";
9910            pr "  free (r);\n";
9911            pr "  return jr;\n"
9912        | RStruct (_, typ) ->
9913            let jtyp = java_name_of_struct typ in
9914            let cols = cols_of_struct typ in
9915            generate_java_struct_return typ jtyp cols
9916        | RStructList (_, typ) ->
9917            let jtyp = java_name_of_struct typ in
9918            let cols = cols_of_struct typ in
9919            generate_java_struct_list_return typ jtyp cols
9920        | RHashtable _ ->
9921            (* XXX *)
9922            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9923            pr "  return NULL;\n"
9924        | RBufferOut _ ->
9925            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9926            pr "  free (r);\n";
9927            pr "  return jr;\n"
9928       );
9929
9930       pr "}\n";
9931       pr "\n"
9932   ) all_functions
9933
9934 and generate_java_struct_return typ jtyp cols =
9935   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9936   pr "  jr = (*env)->AllocObject (env, cl);\n";
9937   List.iter (
9938     function
9939     | name, FString ->
9940         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9941         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9942     | name, FUUID ->
9943         pr "  {\n";
9944         pr "    char s[33];\n";
9945         pr "    memcpy (s, r->%s, 32);\n" name;
9946         pr "    s[32] = 0;\n";
9947         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9948         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9949         pr "  }\n";
9950     | name, FBuffer ->
9951         pr "  {\n";
9952         pr "    int len = r->%s_len;\n" name;
9953         pr "    char s[len+1];\n";
9954         pr "    memcpy (s, r->%s, len);\n" name;
9955         pr "    s[len] = 0;\n";
9956         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9957         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9958         pr "  }\n";
9959     | name, (FBytes|FUInt64|FInt64) ->
9960         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9961         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9962     | name, (FUInt32|FInt32) ->
9963         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9964         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9965     | name, FOptPercent ->
9966         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9967         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9968     | name, FChar ->
9969         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9970         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9971   ) cols;
9972   pr "  free (r);\n";
9973   pr "  return jr;\n"
9974
9975 and generate_java_struct_list_return typ jtyp cols =
9976   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9977   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9978   pr "  for (i = 0; i < r->len; ++i) {\n";
9979   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9980   List.iter (
9981     function
9982     | name, FString ->
9983         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9984         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9985     | name, FUUID ->
9986         pr "    {\n";
9987         pr "      char s[33];\n";
9988         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9989         pr "      s[32] = 0;\n";
9990         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9991         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9992         pr "    }\n";
9993     | name, FBuffer ->
9994         pr "    {\n";
9995         pr "      int len = r->val[i].%s_len;\n" name;
9996         pr "      char s[len+1];\n";
9997         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9998         pr "      s[len] = 0;\n";
9999         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10000         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10001         pr "    }\n";
10002     | name, (FBytes|FUInt64|FInt64) ->
10003         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10004         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10005     | name, (FUInt32|FInt32) ->
10006         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10007         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10008     | name, FOptPercent ->
10009         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10010         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10011     | name, FChar ->
10012         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10013         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10014   ) cols;
10015   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10016   pr "  }\n";
10017   pr "  guestfs_free_%s_list (r);\n" typ;
10018   pr "  return jr;\n"
10019
10020 and generate_java_makefile_inc () =
10021   generate_header HashStyle GPLv2plus;
10022
10023   pr "java_built_sources = \\\n";
10024   List.iter (
10025     fun (typ, jtyp) ->
10026         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10027   ) java_structs;
10028   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10029
10030 and generate_haskell_hs () =
10031   generate_header HaskellStyle LGPLv2plus;
10032
10033   (* XXX We only know how to generate partial FFI for Haskell
10034    * at the moment.  Please help out!
10035    *)
10036   let can_generate style =
10037     match style with
10038     | RErr, _
10039     | RInt _, _
10040     | RInt64 _, _ -> true
10041     | RBool _, _
10042     | RConstString _, _
10043     | RConstOptString _, _
10044     | RString _, _
10045     | RStringList _, _
10046     | RStruct _, _
10047     | RStructList _, _
10048     | RHashtable _, _
10049     | RBufferOut _, _ -> false in
10050
10051   pr "\
10052 {-# INCLUDE <guestfs.h> #-}
10053 {-# LANGUAGE ForeignFunctionInterface #-}
10054
10055 module Guestfs (
10056   create";
10057
10058   (* List out the names of the actions we want to export. *)
10059   List.iter (
10060     fun (name, style, _, _, _, _, _) ->
10061       if can_generate style then pr ",\n  %s" name
10062   ) all_functions;
10063
10064   pr "
10065   ) where
10066
10067 -- Unfortunately some symbols duplicate ones already present
10068 -- in Prelude.  We don't know which, so we hard-code a list
10069 -- here.
10070 import Prelude hiding (truncate)
10071
10072 import Foreign
10073 import Foreign.C
10074 import Foreign.C.Types
10075 import IO
10076 import Control.Exception
10077 import Data.Typeable
10078
10079 data GuestfsS = GuestfsS            -- represents the opaque C struct
10080 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10081 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10082
10083 -- XXX define properly later XXX
10084 data PV = PV
10085 data VG = VG
10086 data LV = LV
10087 data IntBool = IntBool
10088 data Stat = Stat
10089 data StatVFS = StatVFS
10090 data Hashtable = Hashtable
10091
10092 foreign import ccall unsafe \"guestfs_create\" c_create
10093   :: IO GuestfsP
10094 foreign import ccall unsafe \"&guestfs_close\" c_close
10095   :: FunPtr (GuestfsP -> IO ())
10096 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10097   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10098
10099 create :: IO GuestfsH
10100 create = do
10101   p <- c_create
10102   c_set_error_handler p nullPtr nullPtr
10103   h <- newForeignPtr c_close p
10104   return h
10105
10106 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10107   :: GuestfsP -> IO CString
10108
10109 -- last_error :: GuestfsH -> IO (Maybe String)
10110 -- last_error h = do
10111 --   str <- withForeignPtr h (\\p -> c_last_error p)
10112 --   maybePeek peekCString str
10113
10114 last_error :: GuestfsH -> IO (String)
10115 last_error h = do
10116   str <- withForeignPtr h (\\p -> c_last_error p)
10117   if (str == nullPtr)
10118     then return \"no error\"
10119     else peekCString str
10120
10121 ";
10122
10123   (* Generate wrappers for each foreign function. *)
10124   List.iter (
10125     fun (name, style, _, _, _, _, _) ->
10126       if can_generate style then (
10127         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10128         pr "  :: ";
10129         generate_haskell_prototype ~handle:"GuestfsP" style;
10130         pr "\n";
10131         pr "\n";
10132         pr "%s :: " name;
10133         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10134         pr "\n";
10135         pr "%s %s = do\n" name
10136           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10137         pr "  r <- ";
10138         (* Convert pointer arguments using with* functions. *)
10139         List.iter (
10140           function
10141           | FileIn n
10142           | FileOut n
10143           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10144           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10145           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10146           | Bool _ | Int _ | Int64 _ -> ()
10147         ) (snd style);
10148         (* Convert integer arguments. *)
10149         let args =
10150           List.map (
10151             function
10152             | Bool n -> sprintf "(fromBool %s)" n
10153             | Int n -> sprintf "(fromIntegral %s)" n
10154             | Int64 n -> sprintf "(fromIntegral %s)" n
10155             | FileIn n | FileOut n
10156             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10157           ) (snd style) in
10158         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10159           (String.concat " " ("p" :: args));
10160         (match fst style with
10161          | RErr | RInt _ | RInt64 _ | RBool _ ->
10162              pr "  if (r == -1)\n";
10163              pr "    then do\n";
10164              pr "      err <- last_error h\n";
10165              pr "      fail err\n";
10166          | RConstString _ | RConstOptString _ | RString _
10167          | RStringList _ | RStruct _
10168          | RStructList _ | RHashtable _ | RBufferOut _ ->
10169              pr "  if (r == nullPtr)\n";
10170              pr "    then do\n";
10171              pr "      err <- last_error h\n";
10172              pr "      fail err\n";
10173         );
10174         (match fst style with
10175          | RErr ->
10176              pr "    else return ()\n"
10177          | RInt _ ->
10178              pr "    else return (fromIntegral r)\n"
10179          | RInt64 _ ->
10180              pr "    else return (fromIntegral r)\n"
10181          | RBool _ ->
10182              pr "    else return (toBool r)\n"
10183          | RConstString _
10184          | RConstOptString _
10185          | RString _
10186          | RStringList _
10187          | RStruct _
10188          | RStructList _
10189          | RHashtable _
10190          | RBufferOut _ ->
10191              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10192         );
10193         pr "\n";
10194       )
10195   ) all_functions
10196
10197 and generate_haskell_prototype ~handle ?(hs = false) style =
10198   pr "%s -> " handle;
10199   let string = if hs then "String" else "CString" in
10200   let int = if hs then "Int" else "CInt" in
10201   let bool = if hs then "Bool" else "CInt" in
10202   let int64 = if hs then "Integer" else "Int64" in
10203   List.iter (
10204     fun arg ->
10205       (match arg with
10206        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10207        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10208        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10209        | Bool _ -> pr "%s" bool
10210        | Int _ -> pr "%s" int
10211        | Int64 _ -> pr "%s" int
10212        | FileIn _ -> pr "%s" string
10213        | FileOut _ -> pr "%s" string
10214       );
10215       pr " -> ";
10216   ) (snd style);
10217   pr "IO (";
10218   (match fst style with
10219    | RErr -> if not hs then pr "CInt"
10220    | RInt _ -> pr "%s" int
10221    | RInt64 _ -> pr "%s" int64
10222    | RBool _ -> pr "%s" bool
10223    | RConstString _ -> pr "%s" string
10224    | RConstOptString _ -> pr "Maybe %s" string
10225    | RString _ -> pr "%s" string
10226    | RStringList _ -> pr "[%s]" string
10227    | RStruct (_, typ) ->
10228        let name = java_name_of_struct typ in
10229        pr "%s" name
10230    | RStructList (_, typ) ->
10231        let name = java_name_of_struct typ in
10232        pr "[%s]" name
10233    | RHashtable _ -> pr "Hashtable"
10234    | RBufferOut _ -> pr "%s" string
10235   );
10236   pr ")"
10237
10238 and generate_csharp () =
10239   generate_header CPlusPlusStyle LGPLv2plus;
10240
10241   (* XXX Make this configurable by the C# assembly users. *)
10242   let library = "libguestfs.so.0" in
10243
10244   pr "\
10245 // These C# bindings are highly experimental at present.
10246 //
10247 // Firstly they only work on Linux (ie. Mono).  In order to get them
10248 // to work on Windows (ie. .Net) you would need to port the library
10249 // itself to Windows first.
10250 //
10251 // The second issue is that some calls are known to be incorrect and
10252 // can cause Mono to segfault.  Particularly: calls which pass or
10253 // return string[], or return any structure value.  This is because
10254 // we haven't worked out the correct way to do this from C#.
10255 //
10256 // The third issue is that when compiling you get a lot of warnings.
10257 // We are not sure whether the warnings are important or not.
10258 //
10259 // Fourthly we do not routinely build or test these bindings as part
10260 // of the make && make check cycle, which means that regressions might
10261 // go unnoticed.
10262 //
10263 // Suggestions and patches are welcome.
10264
10265 // To compile:
10266 //
10267 // gmcs Libguestfs.cs
10268 // mono Libguestfs.exe
10269 //
10270 // (You'll probably want to add a Test class / static main function
10271 // otherwise this won't do anything useful).
10272
10273 using System;
10274 using System.IO;
10275 using System.Runtime.InteropServices;
10276 using System.Runtime.Serialization;
10277 using System.Collections;
10278
10279 namespace Guestfs
10280 {
10281   class Error : System.ApplicationException
10282   {
10283     public Error (string message) : base (message) {}
10284     protected Error (SerializationInfo info, StreamingContext context) {}
10285   }
10286
10287   class Guestfs
10288   {
10289     IntPtr _handle;
10290
10291     [DllImport (\"%s\")]
10292     static extern IntPtr guestfs_create ();
10293
10294     public Guestfs ()
10295     {
10296       _handle = guestfs_create ();
10297       if (_handle == IntPtr.Zero)
10298         throw new Error (\"could not create guestfs handle\");
10299     }
10300
10301     [DllImport (\"%s\")]
10302     static extern void guestfs_close (IntPtr h);
10303
10304     ~Guestfs ()
10305     {
10306       guestfs_close (_handle);
10307     }
10308
10309     [DllImport (\"%s\")]
10310     static extern string guestfs_last_error (IntPtr h);
10311
10312 " library library library;
10313
10314   (* Generate C# structure bindings.  We prefix struct names with
10315    * underscore because C# cannot have conflicting struct names and
10316    * method names (eg. "class stat" and "stat").
10317    *)
10318   List.iter (
10319     fun (typ, cols) ->
10320       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10321       pr "    public class _%s {\n" typ;
10322       List.iter (
10323         function
10324         | name, FChar -> pr "      char %s;\n" name
10325         | name, FString -> pr "      string %s;\n" name
10326         | name, FBuffer ->
10327             pr "      uint %s_len;\n" name;
10328             pr "      string %s;\n" name
10329         | name, FUUID ->
10330             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10331             pr "      string %s;\n" name
10332         | name, FUInt32 -> pr "      uint %s;\n" name
10333         | name, FInt32 -> pr "      int %s;\n" name
10334         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10335         | name, FInt64 -> pr "      long %s;\n" name
10336         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10337       ) cols;
10338       pr "    }\n";
10339       pr "\n"
10340   ) structs;
10341
10342   (* Generate C# function bindings. *)
10343   List.iter (
10344     fun (name, style, _, _, _, shortdesc, _) ->
10345       let rec csharp_return_type () =
10346         match fst style with
10347         | RErr -> "void"
10348         | RBool n -> "bool"
10349         | RInt n -> "int"
10350         | RInt64 n -> "long"
10351         | RConstString n
10352         | RConstOptString n
10353         | RString n
10354         | RBufferOut n -> "string"
10355         | RStruct (_,n) -> "_" ^ n
10356         | RHashtable n -> "Hashtable"
10357         | RStringList n -> "string[]"
10358         | RStructList (_,n) -> sprintf "_%s[]" n
10359
10360       and c_return_type () =
10361         match fst style with
10362         | RErr
10363         | RBool _
10364         | RInt _ -> "int"
10365         | RInt64 _ -> "long"
10366         | RConstString _
10367         | RConstOptString _
10368         | RString _
10369         | RBufferOut _ -> "string"
10370         | RStruct (_,n) -> "_" ^ n
10371         | RHashtable _
10372         | RStringList _ -> "string[]"
10373         | RStructList (_,n) -> sprintf "_%s[]" n
10374
10375       and c_error_comparison () =
10376         match fst style with
10377         | RErr
10378         | RBool _
10379         | RInt _
10380         | RInt64 _ -> "== -1"
10381         | RConstString _
10382         | RConstOptString _
10383         | RString _
10384         | RBufferOut _
10385         | RStruct (_,_)
10386         | RHashtable _
10387         | RStringList _
10388         | RStructList (_,_) -> "== null"
10389
10390       and generate_extern_prototype () =
10391         pr "    static extern %s guestfs_%s (IntPtr h"
10392           (c_return_type ()) name;
10393         List.iter (
10394           function
10395           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10396           | FileIn n | FileOut n ->
10397               pr ", [In] string %s" n
10398           | StringList n | DeviceList n ->
10399               pr ", [In] string[] %s" n
10400           | Bool n ->
10401               pr ", bool %s" n
10402           | Int n ->
10403               pr ", int %s" n
10404           | Int64 n ->
10405               pr ", long %s" n
10406         ) (snd style);
10407         pr ");\n"
10408
10409       and generate_public_prototype () =
10410         pr "    public %s %s (" (csharp_return_type ()) name;
10411         let comma = ref false in
10412         let next () =
10413           if !comma then pr ", ";
10414           comma := true
10415         in
10416         List.iter (
10417           function
10418           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10419           | FileIn n | FileOut n ->
10420               next (); pr "string %s" n
10421           | StringList n | DeviceList n ->
10422               next (); pr "string[] %s" n
10423           | Bool n ->
10424               next (); pr "bool %s" n
10425           | Int n ->
10426               next (); pr "int %s" n
10427           | Int64 n ->
10428               next (); pr "long %s" n
10429         ) (snd style);
10430         pr ")\n"
10431
10432       and generate_call () =
10433         pr "guestfs_%s (_handle" name;
10434         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10435         pr ");\n";
10436       in
10437
10438       pr "    [DllImport (\"%s\")]\n" library;
10439       generate_extern_prototype ();
10440       pr "\n";
10441       pr "    /// <summary>\n";
10442       pr "    /// %s\n" shortdesc;
10443       pr "    /// </summary>\n";
10444       generate_public_prototype ();
10445       pr "    {\n";
10446       pr "      %s r;\n" (c_return_type ());
10447       pr "      r = ";
10448       generate_call ();
10449       pr "      if (r %s)\n" (c_error_comparison ());
10450       pr "        throw new Error (guestfs_last_error (_handle));\n";
10451       (match fst style with
10452        | RErr -> ()
10453        | RBool _ ->
10454            pr "      return r != 0 ? true : false;\n"
10455        | RHashtable _ ->
10456            pr "      Hashtable rr = new Hashtable ();\n";
10457            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10458            pr "        rr.Add (r[i], r[i+1]);\n";
10459            pr "      return rr;\n"
10460        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10461        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10462        | RStructList _ ->
10463            pr "      return r;\n"
10464       );
10465       pr "    }\n";
10466       pr "\n";
10467   ) all_functions_sorted;
10468
10469   pr "  }
10470 }
10471 "
10472
10473 and generate_bindtests () =
10474   generate_header CStyle LGPLv2plus;
10475
10476   pr "\
10477 #include <stdio.h>
10478 #include <stdlib.h>
10479 #include <inttypes.h>
10480 #include <string.h>
10481
10482 #include \"guestfs.h\"
10483 #include \"guestfs-internal.h\"
10484 #include \"guestfs-internal-actions.h\"
10485 #include \"guestfs_protocol.h\"
10486
10487 #define error guestfs_error
10488 #define safe_calloc guestfs_safe_calloc
10489 #define safe_malloc guestfs_safe_malloc
10490
10491 static void
10492 print_strings (char *const *argv)
10493 {
10494   int argc;
10495
10496   printf (\"[\");
10497   for (argc = 0; argv[argc] != NULL; ++argc) {
10498     if (argc > 0) printf (\", \");
10499     printf (\"\\\"%%s\\\"\", argv[argc]);
10500   }
10501   printf (\"]\\n\");
10502 }
10503
10504 /* The test0 function prints its parameters to stdout. */
10505 ";
10506
10507   let test0, tests =
10508     match test_functions with
10509     | [] -> assert false
10510     | test0 :: tests -> test0, tests in
10511
10512   let () =
10513     let (name, style, _, _, _, _, _) = test0 in
10514     generate_prototype ~extern:false ~semicolon:false ~newline:true
10515       ~handle:"g" ~prefix:"guestfs__" name style;
10516     pr "{\n";
10517     List.iter (
10518       function
10519       | Pathname n
10520       | Device n | Dev_or_Path n
10521       | String n
10522       | FileIn n
10523       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10524       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10525       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10526       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10527       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10528       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10529     ) (snd style);
10530     pr "  /* Java changes stdout line buffering so we need this: */\n";
10531     pr "  fflush (stdout);\n";
10532     pr "  return 0;\n";
10533     pr "}\n";
10534     pr "\n" in
10535
10536   List.iter (
10537     fun (name, style, _, _, _, _, _) ->
10538       if String.sub name (String.length name - 3) 3 <> "err" then (
10539         pr "/* Test normal return. */\n";
10540         generate_prototype ~extern:false ~semicolon:false ~newline:true
10541           ~handle:"g" ~prefix:"guestfs__" name style;
10542         pr "{\n";
10543         (match fst style with
10544          | RErr ->
10545              pr "  return 0;\n"
10546          | RInt _ ->
10547              pr "  int r;\n";
10548              pr "  sscanf (val, \"%%d\", &r);\n";
10549              pr "  return r;\n"
10550          | RInt64 _ ->
10551              pr "  int64_t r;\n";
10552              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10553              pr "  return r;\n"
10554          | RBool _ ->
10555              pr "  return STREQ (val, \"true\");\n"
10556          | RConstString _
10557          | RConstOptString _ ->
10558              (* Can't return the input string here.  Return a static
10559               * string so we ensure we get a segfault if the caller
10560               * tries to free it.
10561               *)
10562              pr "  return \"static string\";\n"
10563          | RString _ ->
10564              pr "  return strdup (val);\n"
10565          | RStringList _ ->
10566              pr "  char **strs;\n";
10567              pr "  int n, i;\n";
10568              pr "  sscanf (val, \"%%d\", &n);\n";
10569              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10570              pr "  for (i = 0; i < n; ++i) {\n";
10571              pr "    strs[i] = safe_malloc (g, 16);\n";
10572              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10573              pr "  }\n";
10574              pr "  strs[n] = NULL;\n";
10575              pr "  return strs;\n"
10576          | RStruct (_, typ) ->
10577              pr "  struct guestfs_%s *r;\n" typ;
10578              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10579              pr "  return r;\n"
10580          | RStructList (_, typ) ->
10581              pr "  struct guestfs_%s_list *r;\n" typ;
10582              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10583              pr "  sscanf (val, \"%%d\", &r->len);\n";
10584              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10585              pr "  return r;\n"
10586          | RHashtable _ ->
10587              pr "  char **strs;\n";
10588              pr "  int n, i;\n";
10589              pr "  sscanf (val, \"%%d\", &n);\n";
10590              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10591              pr "  for (i = 0; i < n; ++i) {\n";
10592              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10593              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10594              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10595              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10596              pr "  }\n";
10597              pr "  strs[n*2] = NULL;\n";
10598              pr "  return strs;\n"
10599          | RBufferOut _ ->
10600              pr "  return strdup (val);\n"
10601         );
10602         pr "}\n";
10603         pr "\n"
10604       ) else (
10605         pr "/* Test error return. */\n";
10606         generate_prototype ~extern:false ~semicolon:false ~newline:true
10607           ~handle:"g" ~prefix:"guestfs__" name style;
10608         pr "{\n";
10609         pr "  error (g, \"error\");\n";
10610         (match fst style with
10611          | RErr | RInt _ | RInt64 _ | RBool _ ->
10612              pr "  return -1;\n"
10613          | RConstString _ | RConstOptString _
10614          | RString _ | RStringList _ | RStruct _
10615          | RStructList _
10616          | RHashtable _
10617          | RBufferOut _ ->
10618              pr "  return NULL;\n"
10619         );
10620         pr "}\n";
10621         pr "\n"
10622       )
10623   ) tests
10624
10625 and generate_ocaml_bindtests () =
10626   generate_header OCamlStyle GPLv2plus;
10627
10628   pr "\
10629 let () =
10630   let g = Guestfs.create () in
10631 ";
10632
10633   let mkargs args =
10634     String.concat " " (
10635       List.map (
10636         function
10637         | CallString s -> "\"" ^ s ^ "\""
10638         | CallOptString None -> "None"
10639         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10640         | CallStringList xs ->
10641             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10642         | CallInt i when i >= 0 -> string_of_int i
10643         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10644         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10645         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10646         | CallBool b -> string_of_bool b
10647       ) args
10648     )
10649   in
10650
10651   generate_lang_bindtests (
10652     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10653   );
10654
10655   pr "print_endline \"EOF\"\n"
10656
10657 and generate_perl_bindtests () =
10658   pr "#!/usr/bin/perl -w\n";
10659   generate_header HashStyle GPLv2plus;
10660
10661   pr "\
10662 use strict;
10663
10664 use Sys::Guestfs;
10665
10666 my $g = Sys::Guestfs->new ();
10667 ";
10668
10669   let mkargs args =
10670     String.concat ", " (
10671       List.map (
10672         function
10673         | CallString s -> "\"" ^ s ^ "\""
10674         | CallOptString None -> "undef"
10675         | CallOptString (Some s) -> sprintf "\"%s\"" s
10676         | CallStringList xs ->
10677             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10678         | CallInt i -> string_of_int i
10679         | CallInt64 i -> Int64.to_string i
10680         | CallBool b -> if b then "1" else "0"
10681       ) args
10682     )
10683   in
10684
10685   generate_lang_bindtests (
10686     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10687   );
10688
10689   pr "print \"EOF\\n\"\n"
10690
10691 and generate_python_bindtests () =
10692   generate_header HashStyle GPLv2plus;
10693
10694   pr "\
10695 import guestfs
10696
10697 g = guestfs.GuestFS ()
10698 ";
10699
10700   let mkargs args =
10701     String.concat ", " (
10702       List.map (
10703         function
10704         | CallString s -> "\"" ^ s ^ "\""
10705         | CallOptString None -> "None"
10706         | CallOptString (Some s) -> sprintf "\"%s\"" s
10707         | CallStringList xs ->
10708             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10709         | CallInt i -> string_of_int i
10710         | CallInt64 i -> Int64.to_string i
10711         | CallBool b -> if b then "1" else "0"
10712       ) args
10713     )
10714   in
10715
10716   generate_lang_bindtests (
10717     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10718   );
10719
10720   pr "print \"EOF\"\n"
10721
10722 and generate_ruby_bindtests () =
10723   generate_header HashStyle GPLv2plus;
10724
10725   pr "\
10726 require 'guestfs'
10727
10728 g = Guestfs::create()
10729 ";
10730
10731   let mkargs args =
10732     String.concat ", " (
10733       List.map (
10734         function
10735         | CallString s -> "\"" ^ s ^ "\""
10736         | CallOptString None -> "nil"
10737         | CallOptString (Some s) -> sprintf "\"%s\"" s
10738         | CallStringList xs ->
10739             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10740         | CallInt i -> string_of_int i
10741         | CallInt64 i -> Int64.to_string i
10742         | CallBool b -> string_of_bool b
10743       ) args
10744     )
10745   in
10746
10747   generate_lang_bindtests (
10748     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10749   );
10750
10751   pr "print \"EOF\\n\"\n"
10752
10753 and generate_java_bindtests () =
10754   generate_header CStyle GPLv2plus;
10755
10756   pr "\
10757 import com.redhat.et.libguestfs.*;
10758
10759 public class Bindtests {
10760     public static void main (String[] argv)
10761     {
10762         try {
10763             GuestFS g = new GuestFS ();
10764 ";
10765
10766   let mkargs args =
10767     String.concat ", " (
10768       List.map (
10769         function
10770         | CallString s -> "\"" ^ s ^ "\""
10771         | CallOptString None -> "null"
10772         | CallOptString (Some s) -> sprintf "\"%s\"" s
10773         | CallStringList xs ->
10774             "new String[]{" ^
10775               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10776         | CallInt i -> string_of_int i
10777         | CallInt64 i -> Int64.to_string i
10778         | CallBool b -> string_of_bool b
10779       ) args
10780     )
10781   in
10782
10783   generate_lang_bindtests (
10784     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10785   );
10786
10787   pr "
10788             System.out.println (\"EOF\");
10789         }
10790         catch (Exception exn) {
10791             System.err.println (exn);
10792             System.exit (1);
10793         }
10794     }
10795 }
10796 "
10797
10798 and generate_haskell_bindtests () =
10799   generate_header HaskellStyle GPLv2plus;
10800
10801   pr "\
10802 module Bindtests where
10803 import qualified Guestfs
10804
10805 main = do
10806   g <- Guestfs.create
10807 ";
10808
10809   let mkargs args =
10810     String.concat " " (
10811       List.map (
10812         function
10813         | CallString s -> "\"" ^ s ^ "\""
10814         | CallOptString None -> "Nothing"
10815         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10816         | CallStringList xs ->
10817             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10818         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10819         | CallInt i -> string_of_int i
10820         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10821         | CallInt64 i -> Int64.to_string i
10822         | CallBool true -> "True"
10823         | CallBool false -> "False"
10824       ) args
10825     )
10826   in
10827
10828   generate_lang_bindtests (
10829     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10830   );
10831
10832   pr "  putStrLn \"EOF\"\n"
10833
10834 (* Language-independent bindings tests - we do it this way to
10835  * ensure there is parity in testing bindings across all languages.
10836  *)
10837 and generate_lang_bindtests call =
10838   call "test0" [CallString "abc"; CallOptString (Some "def");
10839                 CallStringList []; CallBool false;
10840                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10841   call "test0" [CallString "abc"; CallOptString None;
10842                 CallStringList []; CallBool false;
10843                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10844   call "test0" [CallString ""; CallOptString (Some "def");
10845                 CallStringList []; CallBool false;
10846                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10847   call "test0" [CallString ""; CallOptString (Some "");
10848                 CallStringList []; CallBool false;
10849                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10850   call "test0" [CallString "abc"; CallOptString (Some "def");
10851                 CallStringList ["1"]; CallBool false;
10852                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10853   call "test0" [CallString "abc"; CallOptString (Some "def");
10854                 CallStringList ["1"; "2"]; CallBool false;
10855                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10856   call "test0" [CallString "abc"; CallOptString (Some "def");
10857                 CallStringList ["1"]; CallBool true;
10858                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10859   call "test0" [CallString "abc"; CallOptString (Some "def");
10860                 CallStringList ["1"]; CallBool false;
10861                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10862   call "test0" [CallString "abc"; CallOptString (Some "def");
10863                 CallStringList ["1"]; CallBool false;
10864                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10865   call "test0" [CallString "abc"; CallOptString (Some "def");
10866                 CallStringList ["1"]; CallBool false;
10867                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10868   call "test0" [CallString "abc"; CallOptString (Some "def");
10869                 CallStringList ["1"]; CallBool false;
10870                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10871   call "test0" [CallString "abc"; CallOptString (Some "def");
10872                 CallStringList ["1"]; CallBool false;
10873                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10874   call "test0" [CallString "abc"; CallOptString (Some "def");
10875                 CallStringList ["1"]; CallBool false;
10876                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10877
10878 (* XXX Add here tests of the return and error functions. *)
10879
10880 (* Code to generator bindings for virt-inspector.  Currently only
10881  * implemented for OCaml code (for virt-p2v 2.0).
10882  *)
10883 let rng_input = "inspector/virt-inspector.rng"
10884
10885 (* Read the input file and parse it into internal structures.  This is
10886  * by no means a complete RELAX NG parser, but is just enough to be
10887  * able to parse the specific input file.
10888  *)
10889 type rng =
10890   | Element of string * rng list        (* <element name=name/> *)
10891   | Attribute of string * rng list        (* <attribute name=name/> *)
10892   | Interleave of rng list                (* <interleave/> *)
10893   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10894   | OneOrMore of rng                        (* <oneOrMore/> *)
10895   | Optional of rng                        (* <optional/> *)
10896   | Choice of string list                (* <choice><value/>*</choice> *)
10897   | Value of string                        (* <value>str</value> *)
10898   | Text                                (* <text/> *)
10899
10900 let rec string_of_rng = function
10901   | Element (name, xs) ->
10902       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10903   | Attribute (name, xs) ->
10904       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10905   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10906   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10907   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10908   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10909   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10910   | Value value -> "Value \"" ^ value ^ "\""
10911   | Text -> "Text"
10912
10913 and string_of_rng_list xs =
10914   String.concat ", " (List.map string_of_rng xs)
10915
10916 let rec parse_rng ?defines context = function
10917   | [] -> []
10918   | Xml.Element ("element", ["name", name], children) :: rest ->
10919       Element (name, parse_rng ?defines context children)
10920       :: parse_rng ?defines context rest
10921   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10922       Attribute (name, parse_rng ?defines context children)
10923       :: parse_rng ?defines context rest
10924   | Xml.Element ("interleave", [], children) :: rest ->
10925       Interleave (parse_rng ?defines context children)
10926       :: parse_rng ?defines context rest
10927   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10928       let rng = parse_rng ?defines context [child] in
10929       (match rng with
10930        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10931        | _ ->
10932            failwithf "%s: <zeroOrMore> contains more than one child element"
10933              context
10934       )
10935   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10936       let rng = parse_rng ?defines context [child] in
10937       (match rng with
10938        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10939        | _ ->
10940            failwithf "%s: <oneOrMore> contains more than one child element"
10941              context
10942       )
10943   | Xml.Element ("optional", [], [child]) :: rest ->
10944       let rng = parse_rng ?defines context [child] in
10945       (match rng with
10946        | [child] -> Optional child :: parse_rng ?defines context rest
10947        | _ ->
10948            failwithf "%s: <optional> contains more than one child element"
10949              context
10950       )
10951   | Xml.Element ("choice", [], children) :: rest ->
10952       let values = List.map (
10953         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10954         | _ ->
10955             failwithf "%s: can't handle anything except <value> in <choice>"
10956               context
10957       ) children in
10958       Choice values
10959       :: parse_rng ?defines context rest
10960   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10961       Value value :: parse_rng ?defines context rest
10962   | Xml.Element ("text", [], []) :: rest ->
10963       Text :: parse_rng ?defines context rest
10964   | Xml.Element ("ref", ["name", name], []) :: rest ->
10965       (* Look up the reference.  Because of limitations in this parser,
10966        * we can't handle arbitrarily nested <ref> yet.  You can only
10967        * use <ref> from inside <start>.
10968        *)
10969       (match defines with
10970        | None ->
10971            failwithf "%s: contains <ref>, but no refs are defined yet" context
10972        | Some map ->
10973            let rng = StringMap.find name map in
10974            rng @ parse_rng ?defines context rest
10975       )
10976   | x :: _ ->
10977       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10978
10979 let grammar =
10980   let xml = Xml.parse_file rng_input in
10981   match xml with
10982   | Xml.Element ("grammar", _,
10983                  Xml.Element ("start", _, gram) :: defines) ->
10984       (* The <define/> elements are referenced in the <start> section,
10985        * so build a map of those first.
10986        *)
10987       let defines = List.fold_left (
10988         fun map ->
10989           function Xml.Element ("define", ["name", name], defn) ->
10990             StringMap.add name defn map
10991           | _ ->
10992               failwithf "%s: expected <define name=name/>" rng_input
10993       ) StringMap.empty defines in
10994       let defines = StringMap.mapi parse_rng defines in
10995
10996       (* Parse the <start> clause, passing the defines. *)
10997       parse_rng ~defines "<start>" gram
10998   | _ ->
10999       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11000         rng_input
11001
11002 let name_of_field = function
11003   | Element (name, _) | Attribute (name, _)
11004   | ZeroOrMore (Element (name, _))
11005   | OneOrMore (Element (name, _))
11006   | Optional (Element (name, _)) -> name
11007   | Optional (Attribute (name, _)) -> name
11008   | Text -> (* an unnamed field in an element *)
11009       "data"
11010   | rng ->
11011       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11012
11013 (* At the moment this function only generates OCaml types.  However we
11014  * should parameterize it later so it can generate types/structs in a
11015  * variety of languages.
11016  *)
11017 let generate_types xs =
11018   (* A simple type is one that can be printed out directly, eg.
11019    * "string option".  A complex type is one which has a name and has
11020    * to be defined via another toplevel definition, eg. a struct.
11021    *
11022    * generate_type generates code for either simple or complex types.
11023    * In the simple case, it returns the string ("string option").  In
11024    * the complex case, it returns the name ("mountpoint").  In the
11025    * complex case it has to print out the definition before returning,
11026    * so it should only be called when we are at the beginning of a
11027    * new line (BOL context).
11028    *)
11029   let rec generate_type = function
11030     | Text ->                                (* string *)
11031         "string", true
11032     | Choice values ->                        (* [`val1|`val2|...] *)
11033         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11034     | ZeroOrMore rng ->                        (* <rng> list *)
11035         let t, is_simple = generate_type rng in
11036         t ^ " list (* 0 or more *)", is_simple
11037     | OneOrMore rng ->                        (* <rng> list *)
11038         let t, is_simple = generate_type rng in
11039         t ^ " list (* 1 or more *)", is_simple
11040                                         (* virt-inspector hack: bool *)
11041     | Optional (Attribute (name, [Value "1"])) ->
11042         "bool", true
11043     | Optional rng ->                        (* <rng> list *)
11044         let t, is_simple = generate_type rng in
11045         t ^ " option", is_simple
11046                                         (* type name = { fields ... } *)
11047     | Element (name, fields) when is_attrs_interleave fields ->
11048         generate_type_struct name (get_attrs_interleave fields)
11049     | Element (name, [field])                (* type name = field *)
11050     | Attribute (name, [field]) ->
11051         let t, is_simple = generate_type field in
11052         if is_simple then (t, true)
11053         else (
11054           pr "type %s = %s\n" name t;
11055           name, false
11056         )
11057     | Element (name, fields) ->              (* type name = { fields ... } *)
11058         generate_type_struct name fields
11059     | rng ->
11060         failwithf "generate_type failed at: %s" (string_of_rng rng)
11061
11062   and is_attrs_interleave = function
11063     | [Interleave _] -> true
11064     | Attribute _ :: fields -> is_attrs_interleave fields
11065     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11066     | _ -> false
11067
11068   and get_attrs_interleave = function
11069     | [Interleave fields] -> fields
11070     | ((Attribute _) as field) :: fields
11071     | ((Optional (Attribute _)) as field) :: fields ->
11072         field :: get_attrs_interleave fields
11073     | _ -> assert false
11074
11075   and generate_types xs =
11076     List.iter (fun x -> ignore (generate_type x)) xs
11077
11078   and generate_type_struct name fields =
11079     (* Calculate the types of the fields first.  We have to do this
11080      * before printing anything so we are still in BOL context.
11081      *)
11082     let types = List.map fst (List.map generate_type fields) in
11083
11084     (* Special case of a struct containing just a string and another
11085      * field.  Turn it into an assoc list.
11086      *)
11087     match types with
11088     | ["string"; other] ->
11089         let fname1, fname2 =
11090           match fields with
11091           | [f1; f2] -> name_of_field f1, name_of_field f2
11092           | _ -> assert false in
11093         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11094         name, false
11095
11096     | types ->
11097         pr "type %s = {\n" name;
11098         List.iter (
11099           fun (field, ftype) ->
11100             let fname = name_of_field field in
11101             pr "  %s_%s : %s;\n" name fname ftype
11102         ) (List.combine fields types);
11103         pr "}\n";
11104         (* Return the name of this type, and
11105          * false because it's not a simple type.
11106          *)
11107         name, false
11108   in
11109
11110   generate_types xs
11111
11112 let generate_parsers xs =
11113   (* As for generate_type above, generate_parser makes a parser for
11114    * some type, and returns the name of the parser it has generated.
11115    * Because it (may) need to print something, it should always be
11116    * called in BOL context.
11117    *)
11118   let rec generate_parser = function
11119     | Text ->                                (* string *)
11120         "string_child_or_empty"
11121     | Choice values ->                        (* [`val1|`val2|...] *)
11122         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11123           (String.concat "|"
11124              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11125     | ZeroOrMore rng ->                        (* <rng> list *)
11126         let pa = generate_parser rng in
11127         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11128     | OneOrMore rng ->                        (* <rng> list *)
11129         let pa = generate_parser rng in
11130         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11131                                         (* virt-inspector hack: bool *)
11132     | Optional (Attribute (name, [Value "1"])) ->
11133         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11134     | Optional rng ->                        (* <rng> list *)
11135         let pa = generate_parser rng in
11136         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11137                                         (* type name = { fields ... } *)
11138     | Element (name, fields) when is_attrs_interleave fields ->
11139         generate_parser_struct name (get_attrs_interleave fields)
11140     | Element (name, [field]) ->        (* type name = field *)
11141         let pa = generate_parser field in
11142         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11143         pr "let %s =\n" parser_name;
11144         pr "  %s\n" pa;
11145         pr "let parse_%s = %s\n" name parser_name;
11146         parser_name
11147     | Attribute (name, [field]) ->
11148         let pa = generate_parser field in
11149         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11150         pr "let %s =\n" parser_name;
11151         pr "  %s\n" pa;
11152         pr "let parse_%s = %s\n" name parser_name;
11153         parser_name
11154     | Element (name, fields) ->              (* type name = { fields ... } *)
11155         generate_parser_struct name ([], fields)
11156     | rng ->
11157         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11158
11159   and is_attrs_interleave = function
11160     | [Interleave _] -> true
11161     | Attribute _ :: fields -> is_attrs_interleave fields
11162     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11163     | _ -> false
11164
11165   and get_attrs_interleave = function
11166     | [Interleave fields] -> [], fields
11167     | ((Attribute _) as field) :: fields
11168     | ((Optional (Attribute _)) as field) :: fields ->
11169         let attrs, interleaves = get_attrs_interleave fields in
11170         (field :: attrs), interleaves
11171     | _ -> assert false
11172
11173   and generate_parsers xs =
11174     List.iter (fun x -> ignore (generate_parser x)) xs
11175
11176   and generate_parser_struct name (attrs, interleaves) =
11177     (* Generate parsers for the fields first.  We have to do this
11178      * before printing anything so we are still in BOL context.
11179      *)
11180     let fields = attrs @ interleaves in
11181     let pas = List.map generate_parser fields in
11182
11183     (* Generate an intermediate tuple from all the fields first.
11184      * If the type is just a string + another field, then we will
11185      * return this directly, otherwise it is turned into a record.
11186      *
11187      * RELAX NG note: This code treats <interleave> and plain lists of
11188      * fields the same.  In other words, it doesn't bother enforcing
11189      * any ordering of fields in the XML.
11190      *)
11191     pr "let parse_%s x =\n" name;
11192     pr "  let t = (\n    ";
11193     let comma = ref false in
11194     List.iter (
11195       fun x ->
11196         if !comma then pr ",\n    ";
11197         comma := true;
11198         match x with
11199         | Optional (Attribute (fname, [field])), pa ->
11200             pr "%s x" pa
11201         | Optional (Element (fname, [field])), pa ->
11202             pr "%s (optional_child %S x)" pa fname
11203         | Attribute (fname, [Text]), _ ->
11204             pr "attribute %S x" fname
11205         | (ZeroOrMore _ | OneOrMore _), pa ->
11206             pr "%s x" pa
11207         | Text, pa ->
11208             pr "%s x" pa
11209         | (field, pa) ->
11210             let fname = name_of_field field in
11211             pr "%s (child %S x)" pa fname
11212     ) (List.combine fields pas);
11213     pr "\n  ) in\n";
11214
11215     (match fields with
11216      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11217          pr "  t\n"
11218
11219      | _ ->
11220          pr "  (Obj.magic t : %s)\n" name
11221 (*
11222          List.iter (
11223            function
11224            | (Optional (Attribute (fname, [field])), pa) ->
11225                pr "  %s_%s =\n" name fname;
11226                pr "    %s x;\n" pa
11227            | (Optional (Element (fname, [field])), pa) ->
11228                pr "  %s_%s =\n" name fname;
11229                pr "    (let x = optional_child %S x in\n" fname;
11230                pr "     %s x);\n" pa
11231            | (field, pa) ->
11232                let fname = name_of_field field in
11233                pr "  %s_%s =\n" name fname;
11234                pr "    (let x = child %S x in\n" fname;
11235                pr "     %s x);\n" pa
11236          ) (List.combine fields pas);
11237          pr "}\n"
11238 *)
11239     );
11240     sprintf "parse_%s" name
11241   in
11242
11243   generate_parsers xs
11244
11245 (* Generate ocaml/guestfs_inspector.mli. *)
11246 let generate_ocaml_inspector_mli () =
11247   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11248
11249   pr "\
11250 (** This is an OCaml language binding to the external [virt-inspector]
11251     program.
11252
11253     For more information, please read the man page [virt-inspector(1)].
11254 *)
11255
11256 ";
11257
11258   generate_types grammar;
11259   pr "(** The nested information returned from the {!inspect} function. *)\n";
11260   pr "\n";
11261
11262   pr "\
11263 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11264 (** To inspect a libvirt domain called [name], pass a singleton
11265     list: [inspect [name]].  When using libvirt only, you may
11266     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11267
11268     To inspect a disk image or images, pass a list of the filenames
11269     of the disk images: [inspect filenames]
11270
11271     This function inspects the given guest or disk images and
11272     returns a list of operating system(s) found and a large amount
11273     of information about them.  In the vast majority of cases,
11274     a virtual machine only contains a single operating system.
11275
11276     If the optional [~xml] parameter is given, then this function
11277     skips running the external virt-inspector program and just
11278     parses the given XML directly (which is expected to be XML
11279     produced from a previous run of virt-inspector).  The list of
11280     names and connect URI are ignored in this case.
11281
11282     This function can throw a wide variety of exceptions, for example
11283     if the external virt-inspector program cannot be found, or if
11284     it doesn't generate valid XML.
11285 *)
11286 "
11287
11288 (* Generate ocaml/guestfs_inspector.ml. *)
11289 let generate_ocaml_inspector_ml () =
11290   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11291
11292   pr "open Unix\n";
11293   pr "\n";
11294
11295   generate_types grammar;
11296   pr "\n";
11297
11298   pr "\
11299 (* Misc functions which are used by the parser code below. *)
11300 let first_child = function
11301   | Xml.Element (_, _, c::_) -> c
11302   | Xml.Element (name, _, []) ->
11303       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11304   | Xml.PCData str ->
11305       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11306
11307 let string_child_or_empty = function
11308   | Xml.Element (_, _, [Xml.PCData s]) -> s
11309   | Xml.Element (_, _, []) -> \"\"
11310   | Xml.Element (x, _, _) ->
11311       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11312                 x ^ \" instead\")
11313   | Xml.PCData str ->
11314       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11315
11316 let optional_child name xml =
11317   let children = Xml.children xml in
11318   try
11319     Some (List.find (function
11320                      | Xml.Element (n, _, _) when n = name -> true
11321                      | _ -> false) children)
11322   with
11323     Not_found -> None
11324
11325 let child name xml =
11326   match optional_child name xml with
11327   | Some c -> c
11328   | None ->
11329       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11330
11331 let attribute name xml =
11332   try Xml.attrib xml name
11333   with Xml.No_attribute _ ->
11334     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11335
11336 ";
11337
11338   generate_parsers grammar;
11339   pr "\n";
11340
11341   pr "\
11342 (* Run external virt-inspector, then use parser to parse the XML. *)
11343 let inspect ?connect ?xml names =
11344   let xml =
11345     match xml with
11346     | None ->
11347         if names = [] then invalid_arg \"inspect: no names given\";
11348         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11349           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11350           names in
11351         let cmd = List.map Filename.quote cmd in
11352         let cmd = String.concat \" \" cmd in
11353         let chan = open_process_in cmd in
11354         let xml = Xml.parse_in chan in
11355         (match close_process_in chan with
11356          | WEXITED 0 -> ()
11357          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11358          | WSIGNALED i | WSTOPPED i ->
11359              failwith (\"external virt-inspector command died or stopped on sig \" ^
11360                        string_of_int i)
11361         );
11362         xml
11363     | Some doc ->
11364         Xml.parse_string doc in
11365   parse_operatingsystems xml
11366 "
11367
11368 (* This is used to generate the src/MAX_PROC_NR file which
11369  * contains the maximum procedure number, a surrogate for the
11370  * ABI version number.  See src/Makefile.am for the details.
11371  *)
11372 and generate_max_proc_nr () =
11373   let proc_nrs = List.map (
11374     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11375   ) daemon_functions in
11376
11377   let max_proc_nr = List.fold_left max 0 proc_nrs in
11378
11379   pr "%d\n" max_proc_nr
11380
11381 let output_to filename k =
11382   let filename_new = filename ^ ".new" in
11383   chan := open_out filename_new;
11384   k ();
11385   close_out !chan;
11386   chan := Pervasives.stdout;
11387
11388   (* Is the new file different from the current file? *)
11389   if Sys.file_exists filename && files_equal filename filename_new then
11390     unlink filename_new                 (* same, so skip it *)
11391   else (
11392     (* different, overwrite old one *)
11393     (try chmod filename 0o644 with Unix_error _ -> ());
11394     rename filename_new filename;
11395     chmod filename 0o444;
11396     printf "written %s\n%!" filename;
11397   )
11398
11399 let perror msg = function
11400   | Unix_error (err, _, _) ->
11401       eprintf "%s: %s\n" msg (error_message err)
11402   | exn ->
11403       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11404
11405 (* Main program. *)
11406 let () =
11407   let lock_fd =
11408     try openfile "HACKING" [O_RDWR] 0
11409     with
11410     | Unix_error (ENOENT, _, _) ->
11411         eprintf "\
11412 You are probably running this from the wrong directory.
11413 Run it from the top source directory using the command
11414   src/generator.ml
11415 ";
11416         exit 1
11417     | exn ->
11418         perror "open: HACKING" exn;
11419         exit 1 in
11420
11421   (* Acquire a lock so parallel builds won't try to run the generator
11422    * twice at the same time.  Subsequent builds will wait for the first
11423    * one to finish.  Note the lock is released implicitly when the
11424    * program exits.
11425    *)
11426   (try lockf lock_fd F_LOCK 1
11427    with exn ->
11428      perror "lock: HACKING" exn;
11429      exit 1);
11430
11431   check_functions ();
11432
11433   output_to "src/guestfs_protocol.x" generate_xdr;
11434   output_to "src/guestfs-structs.h" generate_structs_h;
11435   output_to "src/guestfs-actions.h" generate_actions_h;
11436   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11437   output_to "src/guestfs-actions.c" generate_client_actions;
11438   output_to "src/guestfs-bindtests.c" generate_bindtests;
11439   output_to "src/guestfs-structs.pod" generate_structs_pod;
11440   output_to "src/guestfs-actions.pod" generate_actions_pod;
11441   output_to "src/guestfs-availability.pod" generate_availability_pod;
11442   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11443   output_to "src/libguestfs.syms" generate_linker_script;
11444   output_to "daemon/actions.h" generate_daemon_actions_h;
11445   output_to "daemon/stubs.c" generate_daemon_actions;
11446   output_to "daemon/names.c" generate_daemon_names;
11447   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11448   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11449   output_to "capitests/tests.c" generate_tests;
11450   output_to "fish/cmds.c" generate_fish_cmds;
11451   output_to "fish/completion.c" generate_fish_completion;
11452   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11453   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11454   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11455   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11456   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11457   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11458   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11459   output_to "perl/Guestfs.xs" generate_perl_xs;
11460   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11461   output_to "perl/bindtests.pl" generate_perl_bindtests;
11462   output_to "python/guestfs-py.c" generate_python_c;
11463   output_to "python/guestfs.py" generate_python_py;
11464   output_to "python/bindtests.py" generate_python_bindtests;
11465   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11466   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11467   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11468
11469   List.iter (
11470     fun (typ, jtyp) ->
11471       let cols = cols_of_struct typ in
11472       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11473       output_to filename (generate_java_struct jtyp cols);
11474   ) java_structs;
11475
11476   output_to "java/Makefile.inc" generate_java_makefile_inc;
11477   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11478   output_to "java/Bindtests.java" generate_java_bindtests;
11479   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11480   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11481   output_to "csharp/Libguestfs.cs" generate_csharp;
11482
11483   (* Always generate this file last, and unconditionally.  It's used
11484    * by the Makefile to know when we must re-run the generator.
11485    *)
11486   let chan = open_out "src/stamp-generator" in
11487   fprintf chan "1\n";
11488   close_out chan;
11489
11490   printf "generated %d lines of code\n" !lines