Clarify sparse behaviour of truncate-size command.
[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, [OptString "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, [OptString "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 dynamic linker functions
795 to find out if this symbol exists (if it doesn't, then
796 it's an earlier version).
797
798 The call returns a structure with four elements.  The first
799 three (C<major>, C<minor> and C<release>) are numbers and
800 correspond to the usual version triplet.  The fourth element
801 (C<extra>) is a string and is normally empty, but may be
802 used for distro-specific information.
803
804 To construct the original version string:
805 C<$major.$minor.$release$extra>
806
807 I<Note:> Don't use this call to test for availability
808 of features.  Distro backports makes this unreliable.  Use
809 C<guestfs_available> instead.");
810
811   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
812    [InitNone, Always, TestOutputTrue (
813       [["set_selinux"; "true"];
814        ["get_selinux"]])],
815    "set SELinux enabled or disabled at appliance boot",
816    "\
817 This sets the selinux flag that is passed to the appliance
818 at boot time.  The default is C<selinux=0> (disabled).
819
820 Note that if SELinux is enabled, it is always in
821 Permissive mode (C<enforcing=0>).
822
823 For more information on the architecture of libguestfs,
824 see L<guestfs(3)>.");
825
826   ("get_selinux", (RBool "selinux", []), -1, [],
827    [],
828    "get SELinux enabled flag",
829    "\
830 This returns the current setting of the selinux flag which
831 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
832
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
835
836   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
837    [InitNone, Always, TestOutputFalse (
838       [["set_trace"; "false"];
839        ["get_trace"]])],
840    "enable or disable command traces",
841    "\
842 If the command trace flag is set to 1, then commands are
843 printed on stdout before they are executed in a format
844 which is very similar to the one used by guestfish.  In
845 other words, you can run a program with this enabled, and
846 you will get out a script which you can feed to guestfish
847 to perform the same set of actions.
848
849 If you want to trace C API calls into libguestfs (and
850 other libraries) then possibly a better way is to use
851 the external ltrace(1) command.
852
853 Command traces are disabled unless the environment variable
854 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
855
856   ("get_trace", (RBool "trace", []), -1, [],
857    [],
858    "get command trace enabled flag",
859    "\
860 Return the command trace flag.");
861
862   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
863    [InitNone, Always, TestOutputFalse (
864       [["set_direct"; "false"];
865        ["get_direct"]])],
866    "enable or disable direct appliance mode",
867    "\
868 If the direct appliance mode flag is enabled, then stdin and
869 stdout are passed directly through to the appliance once it
870 is launched.
871
872 One consequence of this is that log messages aren't caught
873 by the library and handled by C<guestfs_set_log_message_callback>,
874 but go straight to stdout.
875
876 You probably don't want to use this unless you know what you
877 are doing.
878
879 The default is disabled.");
880
881   ("get_direct", (RBool "direct", []), -1, [],
882    [],
883    "get direct appliance mode flag",
884    "\
885 Return the direct appliance mode flag.");
886
887   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
888    [InitNone, Always, TestOutputTrue (
889       [["set_recovery_proc"; "true"];
890        ["get_recovery_proc"]])],
891    "enable or disable the recovery process",
892    "\
893 If this is called with the parameter C<false> then
894 C<guestfs_launch> does not create a recovery process.  The
895 purpose of the recovery process is to stop runaway qemu
896 processes in the case where the main program aborts abruptly.
897
898 This only has any effect if called before C<guestfs_launch>,
899 and the default is true.
900
901 About the only time when you would want to disable this is
902 if the main process will fork itself into the background
903 (\"daemonize\" itself).  In this case the recovery process
904 thinks that the main program has disappeared and so kills
905 qemu, which is not very helpful.");
906
907   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
908    [],
909    "get recovery process enabled flag",
910    "\
911 Return the recovery process enabled flag.");
912
913   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
914    [],
915    "add a drive specifying the QEMU block emulation to use",
916    "\
917 This is the same as C<guestfs_add_drive> but it allows you
918 to specify the QEMU interface emulation to use at run time.");
919
920   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive read-only specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive_ro> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927 ]
928
929 (* daemon_functions are any functions which cause some action
930  * to take place in the daemon.
931  *)
932
933 let daemon_functions = [
934   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
935    [InitEmpty, Always, TestOutput (
936       [["part_disk"; "/dev/sda"; "mbr"];
937        ["mkfs"; "ext2"; "/dev/sda1"];
938        ["mount"; "/dev/sda1"; "/"];
939        ["write_file"; "/new"; "new file contents"; "0"];
940        ["cat"; "/new"]], "new file contents")],
941    "mount a guest disk at a position in the filesystem",
942    "\
943 Mount a guest disk at a position in the filesystem.  Block devices
944 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
945 the guest.  If those block devices contain partitions, they will have
946 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
947 names can be used.
948
949 The rules are the same as for L<mount(2)>:  A filesystem must
950 first be mounted on C</> before others can be mounted.  Other
951 filesystems can only be mounted on directories which already
952 exist.
953
954 The mounted filesystem is writable, if we have sufficient permissions
955 on the underlying device.
956
957 B<Important note:>
958 When you use this call, the filesystem options C<sync> and C<noatime>
959 are set implicitly.  This was originally done because we thought it
960 would improve reliability, but it turns out that I<-o sync> has a
961 very large negative performance impact and negligible effect on
962 reliability.  Therefore we recommend that you avoid using
963 C<guestfs_mount> in any code that needs performance, and instead
964 use C<guestfs_mount_options> (use an empty string for the first
965 parameter if you don't want any options).");
966
967   ("sync", (RErr, []), 2, [],
968    [ InitEmpty, Always, TestRun [["sync"]]],
969    "sync disks, writes are flushed through to the disk image",
970    "\
971 This syncs the disk, so that any writes are flushed through to the
972 underlying disk image.
973
974 You should always call this if you have modified a disk image, before
975 closing the handle.");
976
977   ("touch", (RErr, [Pathname "path"]), 3, [],
978    [InitBasicFS, Always, TestOutputTrue (
979       [["touch"; "/new"];
980        ["exists"; "/new"]])],
981    "update file timestamps or create a new file",
982    "\
983 Touch acts like the L<touch(1)> command.  It can be used to
984 update the timestamps on a file, or, if the file does not exist,
985 to create a new zero-length file.");
986
987   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
988    [InitISOFS, Always, TestOutput (
989       [["cat"; "/known-2"]], "abcdef\n")],
990    "list the contents of a file",
991    "\
992 Return the contents of the file named C<path>.
993
994 Note that this function cannot correctly handle binary files
995 (specifically, files containing C<\\0> character which is treated
996 as end of string).  For those you need to use the C<guestfs_read_file>
997 or C<guestfs_download> functions which have a more complex interface.");
998
999   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1000    [], (* XXX Tricky to test because it depends on the exact format
1001         * of the 'ls -l' command, which changes between F10 and F11.
1002         *)
1003    "list the files in a directory (long format)",
1004    "\
1005 List the files in C<directory> (relative to the root directory,
1006 there is no cwd) in the format of 'ls -la'.
1007
1008 This command is mostly useful for interactive sessions.  It
1009 is I<not> intended that you try to parse the output string.");
1010
1011   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1012    [InitBasicFS, Always, TestOutputList (
1013       [["touch"; "/new"];
1014        ["touch"; "/newer"];
1015        ["touch"; "/newest"];
1016        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1017    "list the files in a directory",
1018    "\
1019 List the files in C<directory> (relative to the root directory,
1020 there is no cwd).  The '.' and '..' entries are not returned, but
1021 hidden files are shown.
1022
1023 This command is mostly useful for interactive sessions.  Programs
1024 should probably use C<guestfs_readdir> instead.");
1025
1026   ("list_devices", (RStringList "devices", []), 7, [],
1027    [InitEmpty, Always, TestOutputListOfDevices (
1028       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1029    "list the block devices",
1030    "\
1031 List all the block devices.
1032
1033 The full block device names are returned, eg. C</dev/sda>");
1034
1035   ("list_partitions", (RStringList "partitions", []), 8, [],
1036    [InitBasicFS, Always, TestOutputListOfDevices (
1037       [["list_partitions"]], ["/dev/sda1"]);
1038     InitEmpty, Always, TestOutputListOfDevices (
1039       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1040        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1041    "list the partitions",
1042    "\
1043 List all the partitions detected on all block devices.
1044
1045 The full partition device names are returned, eg. C</dev/sda1>
1046
1047 This does not return logical volumes.  For that you will need to
1048 call C<guestfs_lvs>.");
1049
1050   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1051    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1052       [["pvs"]], ["/dev/sda1"]);
1053     InitEmpty, Always, TestOutputListOfDevices (
1054       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1055        ["pvcreate"; "/dev/sda1"];
1056        ["pvcreate"; "/dev/sda2"];
1057        ["pvcreate"; "/dev/sda3"];
1058        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1059    "list the LVM physical volumes (PVs)",
1060    "\
1061 List all the physical volumes detected.  This is the equivalent
1062 of the L<pvs(8)> command.
1063
1064 This returns a list of just the device names that contain
1065 PVs (eg. C</dev/sda2>).
1066
1067 See also C<guestfs_pvs_full>.");
1068
1069   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1070    [InitBasicFSonLVM, Always, TestOutputList (
1071       [["vgs"]], ["VG"]);
1072     InitEmpty, Always, TestOutputList (
1073       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1074        ["pvcreate"; "/dev/sda1"];
1075        ["pvcreate"; "/dev/sda2"];
1076        ["pvcreate"; "/dev/sda3"];
1077        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1078        ["vgcreate"; "VG2"; "/dev/sda3"];
1079        ["vgs"]], ["VG1"; "VG2"])],
1080    "list the LVM volume groups (VGs)",
1081    "\
1082 List all the volumes groups detected.  This is the equivalent
1083 of the L<vgs(8)> command.
1084
1085 This returns a list of just the volume group names that were
1086 detected (eg. C<VolGroup00>).
1087
1088 See also C<guestfs_vgs_full>.");
1089
1090   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1091    [InitBasicFSonLVM, Always, TestOutputList (
1092       [["lvs"]], ["/dev/VG/LV"]);
1093     InitEmpty, Always, TestOutputList (
1094       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1095        ["pvcreate"; "/dev/sda1"];
1096        ["pvcreate"; "/dev/sda2"];
1097        ["pvcreate"; "/dev/sda3"];
1098        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1099        ["vgcreate"; "VG2"; "/dev/sda3"];
1100        ["lvcreate"; "LV1"; "VG1"; "50"];
1101        ["lvcreate"; "LV2"; "VG1"; "50"];
1102        ["lvcreate"; "LV3"; "VG2"; "50"];
1103        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1104    "list the LVM logical volumes (LVs)",
1105    "\
1106 List all the logical volumes detected.  This is the equivalent
1107 of the L<lvs(8)> command.
1108
1109 This returns a list of the logical volume device names
1110 (eg. C</dev/VolGroup00/LogVol00>).
1111
1112 See also C<guestfs_lvs_full>.");
1113
1114   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1115    [], (* XXX how to test? *)
1116    "list the LVM physical volumes (PVs)",
1117    "\
1118 List all the physical volumes detected.  This is the equivalent
1119 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1120
1121   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM volume groups (VGs)",
1124    "\
1125 List all the volumes groups detected.  This is the equivalent
1126 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM logical volumes (LVs)",
1131    "\
1132 List all the logical volumes detected.  This is the equivalent
1133 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1136    [InitISOFS, Always, TestOutputList (
1137       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1138     InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/empty"]], [])],
1140    "read file as lines",
1141    "\
1142 Return the contents of the file named C<path>.
1143
1144 The file contents are returned as a list of lines.  Trailing
1145 C<LF> and C<CRLF> character sequences are I<not> returned.
1146
1147 Note that this function cannot correctly handle binary files
1148 (specifically, files containing C<\\0> character which is treated
1149 as end of line).  For those you need to use the C<guestfs_read_file>
1150 function which has a more complex interface.");
1151
1152   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1153    [], (* XXX Augeas code needs tests. *)
1154    "create a new Augeas handle",
1155    "\
1156 Create a new Augeas handle for editing configuration files.
1157 If there was any previous Augeas handle associated with this
1158 guestfs session, then it is closed.
1159
1160 You must call this before using any other C<guestfs_aug_*>
1161 commands.
1162
1163 C<root> is the filesystem root.  C<root> must not be NULL,
1164 use C</> instead.
1165
1166 The flags are the same as the flags defined in
1167 E<lt>augeas.hE<gt>, the logical I<or> of the following
1168 integers:
1169
1170 =over 4
1171
1172 =item C<AUG_SAVE_BACKUP> = 1
1173
1174 Keep the original file with a C<.augsave> extension.
1175
1176 =item C<AUG_SAVE_NEWFILE> = 2
1177
1178 Save changes into a file with extension C<.augnew>, and
1179 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1180
1181 =item C<AUG_TYPE_CHECK> = 4
1182
1183 Typecheck lenses (can be expensive).
1184
1185 =item C<AUG_NO_STDINC> = 8
1186
1187 Do not use standard load path for modules.
1188
1189 =item C<AUG_SAVE_NOOP> = 16
1190
1191 Make save a no-op, just record what would have been changed.
1192
1193 =item C<AUG_NO_LOAD> = 32
1194
1195 Do not load the tree in C<guestfs_aug_init>.
1196
1197 =back
1198
1199 To close the handle, you can call C<guestfs_aug_close>.
1200
1201 To find out more about Augeas, see L<http://augeas.net/>.");
1202
1203   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1204    [], (* XXX Augeas code needs tests. *)
1205    "close the current Augeas handle",
1206    "\
1207 Close the current Augeas handle and free up any resources
1208 used by it.  After calling this, you have to call
1209 C<guestfs_aug_init> again before you can use any other
1210 Augeas functions.");
1211
1212   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1213    [], (* XXX Augeas code needs tests. *)
1214    "define an Augeas variable",
1215    "\
1216 Defines an Augeas variable C<name> whose value is the result
1217 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1218 undefined.
1219
1220 On success this returns the number of nodes in C<expr>, or
1221 C<0> if C<expr> evaluates to something which is not a nodeset.");
1222
1223   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1224    [], (* XXX Augeas code needs tests. *)
1225    "define an Augeas node",
1226    "\
1227 Defines a variable C<name> whose value is the result of
1228 evaluating C<expr>.
1229
1230 If C<expr> evaluates to an empty nodeset, a node is created,
1231 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1232 C<name> will be the nodeset containing that single node.
1233
1234 On success this returns a pair containing the
1235 number of nodes in the nodeset, and a boolean flag
1236 if a node was created.");
1237
1238   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1239    [], (* XXX Augeas code needs tests. *)
1240    "look up the value of an Augeas path",
1241    "\
1242 Look up the value associated with C<path>.  If C<path>
1243 matches exactly one node, the C<value> is returned.");
1244
1245   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "set Augeas path to value",
1248    "\
1249 Set the value associated with C<path> to C<value>.");
1250
1251   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1252    [], (* XXX Augeas code needs tests. *)
1253    "insert a sibling Augeas node",
1254    "\
1255 Create a new sibling C<label> for C<path>, inserting it into
1256 the tree before or after C<path> (depending on the boolean
1257 flag C<before>).
1258
1259 C<path> must match exactly one existing node in the tree, and
1260 C<label> must be a label, ie. not contain C</>, C<*> or end
1261 with a bracketed index C<[N]>.");
1262
1263   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "remove an Augeas path",
1266    "\
1267 Remove C<path> and all of its children.
1268
1269 On success this returns the number of entries which were removed.");
1270
1271   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "move Augeas node",
1274    "\
1275 Move the node C<src> to C<dest>.  C<src> must match exactly
1276 one node.  C<dest> is overwritten if it exists.");
1277
1278   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "return Augeas nodes which match augpath",
1281    "\
1282 Returns a list of paths which match the path expression C<path>.
1283 The returned paths are sufficiently qualified so that they match
1284 exactly one node in the current tree.");
1285
1286   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "write all pending Augeas changes to disk",
1289    "\
1290 This writes all pending changes to disk.
1291
1292 The flags which were passed to C<guestfs_aug_init> affect exactly
1293 how files are saved.");
1294
1295   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "load files into the tree",
1298    "\
1299 Load files into the tree.
1300
1301 See C<aug_load> in the Augeas documentation for the full gory
1302 details.");
1303
1304   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "list Augeas nodes under augpath",
1307    "\
1308 This is just a shortcut for listing C<guestfs_aug_match>
1309 C<path/*> and sorting the resulting nodes into alphabetical order.");
1310
1311   ("rm", (RErr, [Pathname "path"]), 29, [],
1312    [InitBasicFS, Always, TestRun
1313       [["touch"; "/new"];
1314        ["rm"; "/new"]];
1315     InitBasicFS, Always, TestLastFail
1316       [["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["mkdir"; "/new"];
1319        ["rm"; "/new"]]],
1320    "remove a file",
1321    "\
1322 Remove the single file C<path>.");
1323
1324   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1325    [InitBasicFS, Always, TestRun
1326       [["mkdir"; "/new"];
1327        ["rmdir"; "/new"]];
1328     InitBasicFS, Always, TestLastFail
1329       [["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["touch"; "/new"];
1332        ["rmdir"; "/new"]]],
1333    "remove a directory",
1334    "\
1335 Remove the single directory C<path>.");
1336
1337   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1338    [InitBasicFS, Always, TestOutputFalse
1339       [["mkdir"; "/new"];
1340        ["mkdir"; "/new/foo"];
1341        ["touch"; "/new/foo/bar"];
1342        ["rm_rf"; "/new"];
1343        ["exists"; "/new"]]],
1344    "remove a file or directory recursively",
1345    "\
1346 Remove the file or directory C<path>, recursively removing the
1347 contents if its a directory.  This is like the C<rm -rf> shell
1348 command.");
1349
1350   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1351    [InitBasicFS, Always, TestOutputTrue
1352       [["mkdir"; "/new"];
1353        ["is_dir"; "/new"]];
1354     InitBasicFS, Always, TestLastFail
1355       [["mkdir"; "/new/foo/bar"]]],
1356    "create a directory",
1357    "\
1358 Create a directory named C<path>.");
1359
1360   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1361    [InitBasicFS, Always, TestOutputTrue
1362       [["mkdir_p"; "/new/foo/bar"];
1363        ["is_dir"; "/new/foo/bar"]];
1364     InitBasicFS, Always, TestOutputTrue
1365       [["mkdir_p"; "/new/foo/bar"];
1366        ["is_dir"; "/new/foo"]];
1367     InitBasicFS, Always, TestOutputTrue
1368       [["mkdir_p"; "/new/foo/bar"];
1369        ["is_dir"; "/new"]];
1370     (* Regression tests for RHBZ#503133: *)
1371     InitBasicFS, Always, TestRun
1372       [["mkdir"; "/new"];
1373        ["mkdir_p"; "/new"]];
1374     InitBasicFS, Always, TestLastFail
1375       [["touch"; "/new"];
1376        ["mkdir_p"; "/new"]]],
1377    "create a directory and parents",
1378    "\
1379 Create a directory named C<path>, creating any parent directories
1380 as necessary.  This is like the C<mkdir -p> shell command.");
1381
1382   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1383    [], (* XXX Need stat command to test *)
1384    "change file mode",
1385    "\
1386 Change the mode (permissions) of C<path> to C<mode>.  Only
1387 numeric modes are supported.
1388
1389 I<Note>: When using this command from guestfish, C<mode>
1390 by default would be decimal, unless you prefix it with
1391 C<0> to get octal, ie. use C<0700> not C<700>.
1392
1393 The mode actually set is affected by the umask.");
1394
1395   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396    [], (* XXX Need stat command to test *)
1397    "change file owner and group",
1398    "\
1399 Change the file owner to C<owner> and group to C<group>.
1400
1401 Only numeric uid and gid are supported.  If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1404
1405   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406    [InitISOFS, Always, TestOutputTrue (
1407       [["exists"; "/empty"]]);
1408     InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/directory"]])],
1410    "test if file or directory exists",
1411    "\
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1414
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1416
1417   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["is_file"; "/known-1"]]);
1420     InitISOFS, Always, TestOutputFalse (
1421       [["is_file"; "/directory"]])],
1422    "test if file exists",
1423    "\
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name.  Note that it returns false for
1426 other objects like directories.
1427
1428 See also C<guestfs_stat>.");
1429
1430   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431    [InitISOFS, Always, TestOutputFalse (
1432       [["is_dir"; "/known-3"]]);
1433     InitISOFS, Always, TestOutputTrue (
1434       [["is_dir"; "/directory"]])],
1435    "test if file exists",
1436    "\
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name.  Note that it returns false for
1439 other objects like files.
1440
1441 See also C<guestfs_stat>.");
1442
1443   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444    [InitEmpty, Always, TestOutputListOfDevices (
1445       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446        ["pvcreate"; "/dev/sda1"];
1447        ["pvcreate"; "/dev/sda2"];
1448        ["pvcreate"; "/dev/sda3"];
1449        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450    "create an LVM physical volume",
1451    "\
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1454 as C</dev/sda1>.");
1455
1456   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457    [InitEmpty, Always, TestOutputList (
1458       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459        ["pvcreate"; "/dev/sda1"];
1460        ["pvcreate"; "/dev/sda2"];
1461        ["pvcreate"; "/dev/sda3"];
1462        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463        ["vgcreate"; "VG2"; "/dev/sda3"];
1464        ["vgs"]], ["VG1"; "VG2"])],
1465    "create an LVM volume group",
1466    "\
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1469
1470   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471    [InitEmpty, Always, TestOutputList (
1472       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473        ["pvcreate"; "/dev/sda1"];
1474        ["pvcreate"; "/dev/sda2"];
1475        ["pvcreate"; "/dev/sda3"];
1476        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477        ["vgcreate"; "VG2"; "/dev/sda3"];
1478        ["lvcreate"; "LV1"; "VG1"; "50"];
1479        ["lvcreate"; "LV2"; "VG1"; "50"];
1480        ["lvcreate"; "LV3"; "VG2"; "50"];
1481        ["lvcreate"; "LV4"; "VG2"; "50"];
1482        ["lvcreate"; "LV5"; "VG2"; "50"];
1483        ["lvs"]],
1484       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486    "create an LVM logical volume",
1487    "\
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1490
1491   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492    [InitEmpty, Always, TestOutput (
1493       [["part_disk"; "/dev/sda"; "mbr"];
1494        ["mkfs"; "ext2"; "/dev/sda1"];
1495        ["mount_options"; ""; "/dev/sda1"; "/"];
1496        ["write_file"; "/new"; "new file contents"; "0"];
1497        ["cat"; "/new"]], "new file contents")],
1498    "make a filesystem",
1499    "\
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume).  The filesystem type is C<fstype>, for
1502 example C<ext3>.");
1503
1504   ("sfdisk", (RErr, [Device "device";
1505                      Int "cyls"; Int "heads"; Int "sectors";
1506                      StringList "lines"]), 43, [DangerWillRobinson],
1507    [],
1508    "create partitions on a block device",
1509    "\
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1512
1513 C<device> should be a block device, for example C</dev/sda>.
1514
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted.  Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1522
1523 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1524 information refer to the L<sfdisk(8)> manpage.
1525
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1529
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1532
1533   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534    [InitBasicFS, Always, TestOutput (
1535       [["write_file"; "/new"; "new file contents"; "0"];
1536        ["cat"; "/new"]], "new file contents");
1537     InitBasicFS, Always, TestOutput (
1538       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539        ["cat"; "/new"]], "\nnew file contents\n");
1540     InitBasicFS, Always, TestOutput (
1541       [["write_file"; "/new"; "\n\n"; "0"];
1542        ["cat"; "/new"]], "\n\n");
1543     InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; ""; "0"];
1545        ["cat"; "/new"]], "");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\n\n\n"; "0"];
1548        ["cat"; "/new"]], "\n\n\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n"; "0"];
1551        ["cat"; "/new"]], "\n")],
1552    "create a file",
1553    "\
1554 This call creates a file called C<path>.  The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1557
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1561
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version.  In the meantime
1565 use C<guestfs_upload>.");
1566
1567   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568    [InitEmpty, Always, TestOutputListOfDevices (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["mounts"]], ["/dev/sda1"]);
1573     InitEmpty, Always, TestOutputList (
1574       [["part_disk"; "/dev/sda"; "mbr"];
1575        ["mkfs"; "ext2"; "/dev/sda1"];
1576        ["mount_options"; ""; "/dev/sda1"; "/"];
1577        ["umount"; "/"];
1578        ["mounts"]], [])],
1579    "unmount a filesystem",
1580    "\
1581 This unmounts the given filesystem.  The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1584
1585   ("mounts", (RStringList "devices", []), 46, [],
1586    [InitBasicFS, Always, TestOutputListOfDevices (
1587       [["mounts"]], ["/dev/sda1"])],
1588    "show mounted filesystems",
1589    "\
1590 This returns the list of currently mounted filesystems.  It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592
1593 Some internal mounts are not shown.
1594
1595 See also: C<guestfs_mountpoints>");
1596
1597   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598    [InitBasicFS, Always, TestOutputList (
1599       [["umount_all"];
1600        ["mounts"]], []);
1601     (* check that umount_all can unmount nested mounts correctly: *)
1602     InitEmpty, Always, TestOutputList (
1603       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604        ["mkfs"; "ext2"; "/dev/sda1"];
1605        ["mkfs"; "ext2"; "/dev/sda2"];
1606        ["mkfs"; "ext2"; "/dev/sda3"];
1607        ["mount_options"; ""; "/dev/sda1"; "/"];
1608        ["mkdir"; "/mp1"];
1609        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610        ["mkdir"; "/mp1/mp2"];
1611        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612        ["mkdir"; "/mp1/mp2/mp3"];
1613        ["umount_all"];
1614        ["mounts"]], [])],
1615    "unmount all filesystems",
1616    "\
1617 This unmounts all mounted filesystems.
1618
1619 Some internal mounts are not unmounted by this call.");
1620
1621   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622    [],
1623    "remove all LVM LVs, VGs and PVs",
1624    "\
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1627
1628   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629    [InitISOFS, Always, TestOutput (
1630       [["file"; "/empty"]], "empty");
1631     InitISOFS, Always, TestOutput (
1632       [["file"; "/known-1"]], "ASCII text");
1633     InitISOFS, Always, TestLastFail (
1634       [["file"; "/notexists"]])],
1635    "determine file type",
1636    "\
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file.  This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1640
1641 This call will also transparently look inside various types
1642 of compressed file.
1643
1644 The exact command which runs is C<file -zbsL path>.  Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1647
1648   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649    [InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 1"]], "Result1");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 2"]], "Result2\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 3"]], "\nResult3");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 4"]], "\nResult4\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 5"]], "\nResult5\n\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 7"]], "");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 8"]], "\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 9"]], "\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693     InitBasicFS, Always, TestLastFail (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command"]])],
1697    "run a command from the guest filesystem",
1698    "\
1699 This call runs a command from the guest filesystem.  The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1703
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters.  The list must be
1707 non-empty (ie. must contain a program name).  Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1710
1711 The return value is anything printed to I<stdout> by
1712 the command.
1713
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message.  The error message
1716 string is the content of I<stderr> from the command.
1717
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>.  If you require a program from
1720 another location, you should provide the full path in the
1721 first parameter.
1722
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places.  It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1727 locations.");
1728
1729   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730    [InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 1"]], ["Result1"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 2"]], ["Result2"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 7"]], []);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 8"]], [""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 9"]], ["";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774    "run a command, returning lines",
1775    "\
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1778
1779 See also: C<guestfs_sh_lines>");
1780
1781   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782    [InitISOFS, Always, TestOutputStruct (
1783       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784    "get file information",
1785    "\
1786 Returns file information for the given C<path>.
1787
1788 This is the same as the C<stat(2)> system call.");
1789
1790   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information for a symbolic link",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1799 refers to.
1800
1801 This is the same as the C<lstat(2)> system call.");
1802
1803   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804    [InitISOFS, Always, TestOutputStruct (
1805       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806    "get file system statistics",
1807    "\
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1811
1812 This is the same as the C<statvfs(2)> system call.");
1813
1814   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1815    [], (* XXX test *)
1816    "get ext2/ext3/ext4 superblock details",
1817    "\
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1820
1821 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1822 manpage for more details.  The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1825
1826   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827    [InitEmpty, Always, TestOutputTrue (
1828       [["blockdev_setro"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-only",
1831    "\
1832 Sets the block device named C<device> to read-only.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837    [InitEmpty, Always, TestOutputFalse (
1838       [["blockdev_setrw"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "set block device to read-write",
1841    "\
1842 Sets the block device named C<device> to read-write.
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847    [InitEmpty, Always, TestOutputTrue (
1848       [["blockdev_setro"; "/dev/sda"];
1849        ["blockdev_getro"; "/dev/sda"]])],
1850    "is block device set to read-only",
1851    "\
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1854
1855 This uses the L<blockdev(8)> command.");
1856
1857   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858    [InitEmpty, Always, TestOutputInt (
1859       [["blockdev_getss"; "/dev/sda"]], 512)],
1860    "get sectorsize of block device",
1861    "\
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1864
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1866 for that).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871    [InitEmpty, Always, TestOutputInt (
1872       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873    "get blocksize of block device",
1874    "\
1875 This returns the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1883    [], (* XXX test *)
1884    "set blocksize of block device",
1885    "\
1886 This sets the block size of a device.
1887
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1890
1891 This uses the L<blockdev(8)> command.");
1892
1893   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894    [InitEmpty, Always, TestOutputInt (
1895       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896    "get total size of device in 512-byte sectors",
1897    "\
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1900
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908    [InitEmpty, Always, TestOutputInt (
1909       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910    "get total size of device in bytes",
1911    "\
1912 This returns the size of the device in bytes.
1913
1914 See also C<guestfs_blockdev_getsz>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_flushbufs"; "/dev/sda"]]],
1921    "flush device buffers",
1922    "\
1923 This tells the kernel to flush internal buffers associated
1924 with C<device>.
1925
1926 This uses the L<blockdev(8)> command.");
1927
1928   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929    [InitEmpty, Always, TestRun
1930       [["blockdev_rereadpt"; "/dev/sda"]]],
1931    "reread partition table",
1932    "\
1933 Reread the partition table on C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938    [InitBasicFS, Always, TestOutput (
1939       (* Pick a file from cwd which isn't likely to change. *)
1940       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941        ["checksum"; "md5"; "/COPYING.LIB"]],
1942       Digest.to_hex (Digest.file "COPYING.LIB"))],
1943    "upload a file from the local machine",
1944    "\
1945 Upload local file C<filename> to C<remotefilename> on the
1946 filesystem.
1947
1948 C<filename> can also be a named pipe.
1949
1950 See also C<guestfs_download>.");
1951
1952   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953    [InitBasicFS, Always, TestOutput (
1954       (* Pick a file from cwd which isn't likely to change. *)
1955       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957        ["upload"; "testdownload.tmp"; "/upload"];
1958        ["checksum"; "md5"; "/upload"]],
1959       Digest.to_hex (Digest.file "COPYING.LIB"))],
1960    "download a file to the local machine",
1961    "\
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1964
1965 C<filename> can also be a named pipe.
1966
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1968
1969   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970    [InitISOFS, Always, TestOutput (
1971       [["checksum"; "crc"; "/known-3"]], "2891671662");
1972     InitISOFS, Always, TestLastFail (
1973       [["checksum"; "crc"; "/notexists"]]);
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986    "compute MD5, SHAx or CRC checksum of file",
1987    "\
1988 This call computes the MD5, SHAx or CRC checksum of the
1989 file named C<path>.
1990
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1993
1994 =over 4
1995
1996 =item C<crc>
1997
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2000
2001 =item C<md5>
2002
2003 Compute the MD5 hash (using the C<md5sum> program).
2004
2005 =item C<sha1>
2006
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2008
2009 =item C<sha224>
2010
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2012
2013 =item C<sha256>
2014
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2016
2017 =item C<sha384>
2018
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2020
2021 =item C<sha512>
2022
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2024
2025 =back
2026
2027 The checksum is returned as a printable string.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2039
2040   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2041    [],
2042    "pack directory into tarfile",
2043    "\
2044 This command packs the contents of C<directory> and downloads
2045 it to local file C<tarfile>.
2046
2047 To download a compressed tarball, use C<guestfs_tgz_out>.");
2048
2049   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2050    [InitBasicFS, Always, TestOutput (
2051       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2052        ["cat"; "/hello"]], "hello\n")],
2053    "unpack compressed tarball to directory",
2054    "\
2055 This command uploads and unpacks local file C<tarball> (a
2056 I<gzip compressed> tar file) into C<directory>.
2057
2058 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2059
2060   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2061    [],
2062    "pack directory into compressed tarball",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarball>.
2066
2067 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2068
2069   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2070    [InitBasicFS, Always, TestLastFail (
2071       [["umount"; "/"];
2072        ["mount_ro"; "/dev/sda1"; "/"];
2073        ["touch"; "/new"]]);
2074     InitBasicFS, Always, TestOutput (
2075       [["write_file"; "/new"; "data"; "0"];
2076        ["umount"; "/"];
2077        ["mount_ro"; "/dev/sda1"; "/"];
2078        ["cat"; "/new"]], "data")],
2079    "mount a guest disk, read-only",
2080    "\
2081 This is the same as the C<guestfs_mount> command, but it
2082 mounts the filesystem with the read-only (I<-o ro>) flag.");
2083
2084   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2085    [],
2086    "mount a guest disk with mount options",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set the mount options as for the
2090 L<mount(8)> I<-o> flag.
2091
2092 If the C<options> parameter is an empty string, then
2093 no options are passed (all options default to whatever
2094 the filesystem uses).");
2095
2096   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097    [],
2098    "mount a guest disk with mount options and vfstype",
2099    "\
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103
2104   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105    [],
2106    "debugging and internals",
2107    "\
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2110 qemu subprocess.
2111
2112 There is no comprehensive help for this command.  You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2115
2116   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117    [InitEmpty, Always, TestOutputList (
2118       [["part_disk"; "/dev/sda"; "mbr"];
2119        ["pvcreate"; "/dev/sda1"];
2120        ["vgcreate"; "VG"; "/dev/sda1"];
2121        ["lvcreate"; "LV1"; "VG"; "50"];
2122        ["lvcreate"; "LV2"; "VG"; "50"];
2123        ["lvremove"; "/dev/VG/LV1"];
2124        ["lvs"]], ["/dev/VG/LV2"]);
2125     InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["lvremove"; "/dev/VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG"];
2140        ["vgs"]], ["VG"])],
2141    "remove an LVM logical volume",
2142    "\
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2145
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2148
2149   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150    [InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["vgremove"; "VG"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputList (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["vgs"]], [])],
2166    "remove an LVM volume group",
2167    "\
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169
2170 This also forcibly removes all logical volumes in the volume
2171 group (if any).");
2172
2173   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174    [InitEmpty, Always, TestOutputListOfDevices (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["pvremove"; "/dev/sda1"];
2182        ["lvs"]], []);
2183     InitEmpty, Always, TestOutputListOfDevices (
2184       [["part_disk"; "/dev/sda"; "mbr"];
2185        ["pvcreate"; "/dev/sda1"];
2186        ["vgcreate"; "VG"; "/dev/sda1"];
2187        ["lvcreate"; "LV1"; "VG"; "50"];
2188        ["lvcreate"; "LV2"; "VG"; "50"];
2189        ["vgremove"; "VG"];
2190        ["pvremove"; "/dev/sda1"];
2191        ["vgs"]], []);
2192     InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["pvs"]], [])],
2201    "remove an LVM physical volume",
2202    "\
2203 This wipes a physical volume C<device> so that LVM will no longer
2204 recognise it.
2205
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2209
2210   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211    [InitBasicFS, Always, TestOutput (
2212       [["set_e2label"; "/dev/sda1"; "testlabel"];
2213        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214    "set the ext2/3/4 filesystem label",
2215    "\
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>.  Filesystem labels are limited to
2218 16 characters.
2219
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2222
2223   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224    [],
2225    "get the ext2/3/4 filesystem label",
2226    "\
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2228 C<device>.");
2229
2230   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231    (let uuid = uuidgen () in
2232     [InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; uuid];
2234         ["get_e2uuid"; "/dev/sda1"]], uuid);
2235      InitBasicFS, Always, TestOutput (
2236        [["set_e2uuid"; "/dev/sda1"; "clear"];
2237         ["get_e2uuid"; "/dev/sda1"]], "");
2238      (* We can't predict what UUIDs will be, so just check the commands run. *)
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243    "set the ext2/3/4 filesystem UUID",
2244    "\
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>.  The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2249
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2252
2253   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254    [],
2255    "get the ext2/3/4 filesystem UUID",
2256    "\
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 C<device>.");
2259
2260   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2261    [InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264     InitBasicFS, Always, TestOutputInt (
2265       [["umount"; "/dev/sda1"];
2266        ["zero"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268    "run the filesystem checker",
2269    "\
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2272
2273 The returned integer is the status.  See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2275
2276 Notes:
2277
2278 =over 4
2279
2280 =item *
2281
2282 Multiple status codes can be summed together.
2283
2284 =item *
2285
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2288
2289 =item *
2290
2291 Checking or repairing NTFS volumes is not supported
2292 (by linux-ntfs).
2293
2294 =back
2295
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297
2298   ("zero", (RErr, [Device "device"]), 85, [],
2299    [InitBasicFS, Always, TestOutput (
2300       [["umount"; "/dev/sda1"];
2301        ["zero"; "/dev/sda1"];
2302        ["file"; "/dev/sda1"]], "data")],
2303    "write zeroes to the device",
2304    "\
2305 This command writes zeroes over the first few blocks of C<device>.
2306
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device).  It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2310
2311 See also: C<guestfs_scrub_device>.");
2312
2313   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314    (* Test disabled because grub-install incompatible with virtio-blk driver.
2315     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316     *)
2317    [InitBasicFS, Disabled, TestOutputTrue (
2318       [["grub_install"; "/"; "/dev/sda1"];
2319        ["is_dir"; "/boot"]])],
2320    "install GRUB",
2321    "\
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2324
2325   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326    [InitBasicFS, Always, TestOutput (
2327       [["write_file"; "/old"; "file content"; "0"];
2328        ["cp"; "/old"; "/new"];
2329        ["cat"; "/new"]], "file content");
2330     InitBasicFS, Always, TestOutputTrue (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["is_file"; "/old"]]);
2334     InitBasicFS, Always, TestOutput (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["mkdir"; "/dir"];
2337        ["cp"; "/old"; "/dir/new"];
2338        ["cat"; "/dir/new"]], "file content")],
2339    "copy a file",
2340    "\
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2343
2344   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["mkdir"; "/olddir"];
2347        ["mkdir"; "/newdir"];
2348        ["write_file"; "/olddir/file"; "file content"; "0"];
2349        ["cp_a"; "/olddir"; "/newdir"];
2350        ["cat"; "/newdir/olddir/file"]], "file content")],
2351    "copy a file or directory recursively",
2352    "\
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2355
2356   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357    [InitBasicFS, Always, TestOutput (
2358       [["write_file"; "/old"; "file content"; "0"];
2359        ["mv"; "/old"; "/new"];
2360        ["cat"; "/new"]], "file content");
2361     InitBasicFS, Always, TestOutputFalse (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["is_file"; "/old"]])],
2365    "move a file",
2366    "\
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371    [InitEmpty, Always, TestRun (
2372       [["drop_caches"; "3"]])],
2373    "drop kernel page cache, dentries and inodes",
2374    "\
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches.  The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2379
2380 Setting C<whattodrop> to 3 should drop everything.
2381
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2384
2385   ("dmesg", (RString "kmsgs", []), 91, [],
2386    [InitEmpty, Always, TestRun (
2387       [["dmesg"]])],
2388    "return kernel messages",
2389    "\
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel.  This is sometimes useful for extended
2392 debugging of problems.
2393
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2398
2399   ("ping_daemon", (RErr, []), 92, [],
2400    [InitEmpty, Always, TestRun (
2401       [["ping_daemon"]])],
2402    "ping the guest daemon",
2403    "\
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess.  Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2408
2409   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410    [InitBasicFS, Always, TestOutputTrue (
2411       [["write_file"; "/file1"; "contents of a file"; "0"];
2412        ["cp"; "/file1"; "/file2"];
2413        ["equal"; "/file1"; "/file2"]]);
2414     InitBasicFS, Always, TestOutputFalse (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["write_file"; "/file2"; "contents of another file"; "0"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestLastFail (
2419       [["equal"; "/file1"; "/file2"]])],
2420    "test if two files have equal contents",
2421    "\
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2424
2425 The external L<cmp(1)> program is used for the comparison.");
2426
2427   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428    [InitISOFS, Always, TestOutputList (
2429       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430     InitISOFS, Always, TestOutputList (
2431       [["strings"; "/empty"]], [])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Disabled, TestOutputList (
2441       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding of strings that are looked for in
2447 the source file C<path>.
2448
2449 Allowed encodings are:
2450
2451 =over 4
2452
2453 =item s
2454
2455 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2456 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2457
2458 =item S
2459
2460 Single 8-bit-byte characters.
2461
2462 =item b
2463
2464 16-bit big endian strings such as those encoded in
2465 UTF-16BE or UCS-2BE.
2466
2467 =item l (lower case letter L)
2468
2469 16-bit little endian such as UTF-16LE and UCS-2LE.
2470 This is useful for examining binaries in Windows guests.
2471
2472 =item B
2473
2474 32-bit big endian such as UCS-4BE.
2475
2476 =item L
2477
2478 32-bit little endian such as UCS-4LE.
2479
2480 =back
2481
2482 The returned strings are transcoded to UTF-8.");
2483
2484   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2485    [InitISOFS, Always, TestOutput (
2486       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2487     (* Test for RHBZ#501888c2 regression which caused large hexdump
2488      * commands to segfault.
2489      *)
2490     InitISOFS, Always, TestRun (
2491       [["hexdump"; "/100krandom"]])],
2492    "dump a file in hexadecimal",
2493    "\
2494 This runs C<hexdump -C> on the given C<path>.  The result is
2495 the human-readable, canonical hex dump of the file.");
2496
2497   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2498    [InitNone, Always, TestOutput (
2499       [["part_disk"; "/dev/sda"; "mbr"];
2500        ["mkfs"; "ext3"; "/dev/sda1"];
2501        ["mount_options"; ""; "/dev/sda1"; "/"];
2502        ["write_file"; "/new"; "test file"; "0"];
2503        ["umount"; "/dev/sda1"];
2504        ["zerofree"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["cat"; "/new"]], "test file")],
2507    "zero unused inodes and disk blocks on ext2/3 filesystem",
2508    "\
2509 This runs the I<zerofree> program on C<device>.  This program
2510 claims to zero unused inodes and disk blocks on an ext2/3
2511 filesystem, thus making it possible to compress the filesystem
2512 more effectively.
2513
2514 You should B<not> run this program if the filesystem is
2515 mounted.
2516
2517 It is possible that using this program can damage the filesystem
2518 or data on the filesystem.");
2519
2520   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2521    [],
2522    "resize an LVM physical volume",
2523    "\
2524 This resizes (expands or shrinks) an existing LVM physical
2525 volume to match the new size of the underlying device.");
2526
2527   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2528                        Int "cyls"; Int "heads"; Int "sectors";
2529                        String "line"]), 99, [DangerWillRobinson],
2530    [],
2531    "modify a single partition on a block device",
2532    "\
2533 This runs L<sfdisk(8)> option to modify just the single
2534 partition C<n> (note: C<n> counts from 1).
2535
2536 For other parameters, see C<guestfs_sfdisk>.  You should usually
2537 pass C<0> for the cyls/heads/sectors parameters.
2538
2539 See also: C<guestfs_part_add>");
2540
2541   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2542    [],
2543    "display the partition table",
2544    "\
2545 This displays the partition table on C<device>, in the
2546 human-readable output of the L<sfdisk(8)> command.  It is
2547 not intended to be parsed.
2548
2549 See also: C<guestfs_part_list>");
2550
2551   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2552    [],
2553    "display the kernel geometry",
2554    "\
2555 This displays the kernel's idea of the geometry of C<device>.
2556
2557 The result is in human-readable format, and not designed to
2558 be parsed.");
2559
2560   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2561    [],
2562    "display the disk geometry from the partition table",
2563    "\
2564 This displays the disk geometry of C<device> read from the
2565 partition table.  Especially in the case where the underlying
2566 block device has been resized, this can be different from the
2567 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2568
2569 The result is in human-readable format, and not designed to
2570 be parsed.");
2571
2572   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2573    [],
2574    "activate or deactivate all volume groups",
2575    "\
2576 This command activates or (if C<activate> is false) deactivates
2577 all logical volumes in all volume groups.
2578 If activated, then they are made known to the
2579 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2580 then those devices disappear.
2581
2582 This command is the same as running C<vgchange -a y|n>");
2583
2584   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2585    [],
2586    "activate or deactivate some volume groups",
2587    "\
2588 This command activates or (if C<activate> is false) deactivates
2589 all logical volumes in the listed volume groups C<volgroups>.
2590 If activated, then they are made known to the
2591 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2592 then those devices disappear.
2593
2594 This command is the same as running C<vgchange -a y|n volgroups...>
2595
2596 Note that if C<volgroups> is an empty list then B<all> volume groups
2597 are activated or deactivated.");
2598
2599   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2600    [InitNone, Always, TestOutput (
2601       [["part_disk"; "/dev/sda"; "mbr"];
2602        ["pvcreate"; "/dev/sda1"];
2603        ["vgcreate"; "VG"; "/dev/sda1"];
2604        ["lvcreate"; "LV"; "VG"; "10"];
2605        ["mkfs"; "ext2"; "/dev/VG/LV"];
2606        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2607        ["write_file"; "/new"; "test content"; "0"];
2608        ["umount"; "/"];
2609        ["lvresize"; "/dev/VG/LV"; "20"];
2610        ["e2fsck_f"; "/dev/VG/LV"];
2611        ["resize2fs"; "/dev/VG/LV"];
2612        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2613        ["cat"; "/new"]], "test content");
2614     InitNone, Always, TestRun (
2615       (* Make an LV smaller to test RHBZ#587484. *)
2616       [["part_disk"; "/dev/sda"; "mbr"];
2617        ["pvcreate"; "/dev/sda1"];
2618        ["vgcreate"; "VG"; "/dev/sda1"];
2619        ["lvcreate"; "LV"; "VG"; "20"];
2620        ["lvresize"; "/dev/VG/LV"; "10"]])],
2621    "resize an LVM logical volume",
2622    "\
2623 This resizes (expands or shrinks) an existing LVM logical
2624 volume to C<mbytes>.  When reducing, data in the reduced part
2625 is lost.");
2626
2627   ("resize2fs", (RErr, [Device "device"]), 106, [],
2628    [], (* lvresize tests this *)
2629    "resize an ext2/ext3 filesystem",
2630    "\
2631 This resizes an ext2 or ext3 filesystem to match the size of
2632 the underlying device.
2633
2634 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2635 on the C<device> before calling this command.  For unknown reasons
2636 C<resize2fs> sometimes gives an error about this and sometimes not.
2637 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2638 calling this function.");
2639
2640   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2641    [InitBasicFS, Always, TestOutputList (
2642       [["find"; "/"]], ["lost+found"]);
2643     InitBasicFS, Always, TestOutputList (
2644       [["touch"; "/a"];
2645        ["mkdir"; "/b"];
2646        ["touch"; "/b/c"];
2647        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2648     InitBasicFS, Always, TestOutputList (
2649       [["mkdir_p"; "/a/b/c"];
2650        ["touch"; "/a/b/c/d"];
2651        ["find"; "/a/b/"]], ["c"; "c/d"])],
2652    "find all files and directories",
2653    "\
2654 This command lists out all files and directories, recursively,
2655 starting at C<directory>.  It is essentially equivalent to
2656 running the shell command C<find directory -print> but some
2657 post-processing happens on the output, described below.
2658
2659 This returns a list of strings I<without any prefix>.  Thus
2660 if the directory structure was:
2661
2662  /tmp/a
2663  /tmp/b
2664  /tmp/c/d
2665
2666 then the returned list from C<guestfs_find> C</tmp> would be
2667 4 elements:
2668
2669  a
2670  b
2671  c
2672  c/d
2673
2674 If C<directory> is not a directory, then this command returns
2675 an error.
2676
2677 The returned list is sorted.
2678
2679 See also C<guestfs_find0>.");
2680
2681   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2682    [], (* lvresize tests this *)
2683    "check an ext2/ext3 filesystem",
2684    "\
2685 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2686 filesystem checker on C<device>, noninteractively (C<-p>),
2687 even if the filesystem appears to be clean (C<-f>).
2688
2689 This command is only needed because of C<guestfs_resize2fs>
2690 (q.v.).  Normally you should use C<guestfs_fsck>.");
2691
2692   ("sleep", (RErr, [Int "secs"]), 109, [],
2693    [InitNone, Always, TestRun (
2694       [["sleep"; "1"]])],
2695    "sleep for some seconds",
2696    "\
2697 Sleep for C<secs> seconds.");
2698
2699   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2700    [InitNone, Always, TestOutputInt (
2701       [["part_disk"; "/dev/sda"; "mbr"];
2702        ["mkfs"; "ntfs"; "/dev/sda1"];
2703        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2704     InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ext2"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2708    "probe NTFS volume",
2709    "\
2710 This command runs the L<ntfs-3g.probe(8)> command which probes
2711 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2712 be mounted read-write, and some cannot be mounted at all).
2713
2714 C<rw> is a boolean flag.  Set it to true if you want to test
2715 if the volume can be mounted read-write.  Set it to false if
2716 you want to test if the volume can be mounted read-only.
2717
2718 The return value is an integer which C<0> if the operation
2719 would succeed, or some non-zero value documented in the
2720 L<ntfs-3g.probe(8)> manual page.");
2721
2722   ("sh", (RString "output", [String "command"]), 111, [],
2723    [], (* XXX needs tests *)
2724    "run a command via the shell",
2725    "\
2726 This call runs a command from the guest filesystem via the
2727 guest's C</bin/sh>.
2728
2729 This is like C<guestfs_command>, but passes the command to:
2730
2731  /bin/sh -c \"command\"
2732
2733 Depending on the guest's shell, this usually results in
2734 wildcards being expanded, shell expressions being interpolated
2735 and so on.
2736
2737 All the provisos about C<guestfs_command> apply to this call.");
2738
2739   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2740    [], (* XXX needs tests *)
2741    "run a command via the shell returning lines",
2742    "\
2743 This is the same as C<guestfs_sh>, but splits the result
2744 into a list of lines.
2745
2746 See also: C<guestfs_command_lines>");
2747
2748   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2749    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2750     * code in stubs.c, since all valid glob patterns must start with "/".
2751     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2752     *)
2753    [InitBasicFS, Always, TestOutputList (
2754       [["mkdir_p"; "/a/b/c"];
2755        ["touch"; "/a/b/c/d"];
2756        ["touch"; "/a/b/c/e"];
2757        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758     InitBasicFS, Always, TestOutputList (
2759       [["mkdir_p"; "/a/b/c"];
2760        ["touch"; "/a/b/c/d"];
2761        ["touch"; "/a/b/c/e"];
2762        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2763     InitBasicFS, Always, TestOutputList (
2764       [["mkdir_p"; "/a/b/c"];
2765        ["touch"; "/a/b/c/d"];
2766        ["touch"; "/a/b/c/e"];
2767        ["glob_expand"; "/a/*/x/*"]], [])],
2768    "expand a wildcard path",
2769    "\
2770 This command searches for all the pathnames matching
2771 C<pattern> according to the wildcard expansion rules
2772 used by the shell.
2773
2774 If no paths match, then this returns an empty list
2775 (note: not an error).
2776
2777 It is just a wrapper around the C L<glob(3)> function
2778 with flags C<GLOB_MARK|GLOB_BRACE>.
2779 See that manual page for more details.");
2780
2781   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2782    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2783       [["scrub_device"; "/dev/sdc"]])],
2784    "scrub (securely wipe) a device",
2785    "\
2786 This command writes patterns over C<device> to make data retrieval
2787 more difficult.
2788
2789 It is an interface to the L<scrub(1)> program.  See that
2790 manual page for more details.");
2791
2792   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2793    [InitBasicFS, Always, TestRun (
2794       [["write_file"; "/file"; "content"; "0"];
2795        ["scrub_file"; "/file"]])],
2796    "scrub (securely wipe) a file",
2797    "\
2798 This command writes patterns over a file to make data retrieval
2799 more difficult.
2800
2801 The file is I<removed> after scrubbing.
2802
2803 It is an interface to the L<scrub(1)> program.  See that
2804 manual page for more details.");
2805
2806   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2807    [], (* XXX needs testing *)
2808    "scrub (securely wipe) free space",
2809    "\
2810 This command creates the directory C<dir> and then fills it
2811 with files until the filesystem is full, and scrubs the files
2812 as for C<guestfs_scrub_file>, and deletes them.
2813 The intention is to scrub any free space on the partition
2814 containing C<dir>.
2815
2816 It is an interface to the L<scrub(1)> program.  See that
2817 manual page for more details.");
2818
2819   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2820    [InitBasicFS, Always, TestRun (
2821       [["mkdir"; "/tmp"];
2822        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2823    "create a temporary directory",
2824    "\
2825 This command creates a temporary directory.  The
2826 C<template> parameter should be a full pathname for the
2827 temporary directory name with the final six characters being
2828 \"XXXXXX\".
2829
2830 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2831 the second one being suitable for Windows filesystems.
2832
2833 The name of the temporary directory that was created
2834 is returned.
2835
2836 The temporary directory is created with mode 0700
2837 and is owned by root.
2838
2839 The caller is responsible for deleting the temporary
2840 directory and its contents after use.
2841
2842 See also: L<mkdtemp(3)>");
2843
2844   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2845    [InitISOFS, Always, TestOutputInt (
2846       [["wc_l"; "/10klines"]], 10000)],
2847    "count lines in a file",
2848    "\
2849 This command counts the lines in a file, using the
2850 C<wc -l> external command.");
2851
2852   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_w"; "/10klines"]], 10000)],
2855    "count words in a file",
2856    "\
2857 This command counts the words in a file, using the
2858 C<wc -w> external command.");
2859
2860   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2861    [InitISOFS, Always, TestOutputInt (
2862       [["wc_c"; "/100kallspaces"]], 102400)],
2863    "count characters in a file",
2864    "\
2865 This command counts the characters in a file, using the
2866 C<wc -c> external command.");
2867
2868   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2869    [InitISOFS, Always, TestOutputList (
2870       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2871    "return first 10 lines of a file",
2872    "\
2873 This command returns up to the first 10 lines of a file as
2874 a list of strings.");
2875
2876   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2877    [InitISOFS, Always, TestOutputList (
2878       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2879     InitISOFS, Always, TestOutputList (
2880       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881     InitISOFS, Always, TestOutputList (
2882       [["head_n"; "0"; "/10klines"]], [])],
2883    "return first N lines of a file",
2884    "\
2885 If the parameter C<nrlines> is a positive number, this returns the first
2886 C<nrlines> lines of the file C<path>.
2887
2888 If the parameter C<nrlines> is a negative number, this returns lines
2889 from the file C<path>, excluding the last C<nrlines> lines.
2890
2891 If the parameter C<nrlines> is zero, this returns an empty list.");
2892
2893   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2896    "return last 10 lines of a file",
2897    "\
2898 This command returns up to the last 10 lines of a file as
2899 a list of strings.");
2900
2901   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2902    [InitISOFS, Always, TestOutputList (
2903       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2904     InitISOFS, Always, TestOutputList (
2905       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906     InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "0"; "/10klines"]], [])],
2908    "return last N lines of a file",
2909    "\
2910 If the parameter C<nrlines> is a positive number, this returns the last
2911 C<nrlines> lines of the file C<path>.
2912
2913 If the parameter C<nrlines> is a negative number, this returns lines
2914 from the file C<path>, starting with the C<-nrlines>th line.
2915
2916 If the parameter C<nrlines> is zero, this returns an empty list.");
2917
2918   ("df", (RString "output", []), 125, [],
2919    [], (* XXX Tricky to test because it depends on the exact format
2920         * of the 'df' command and other imponderables.
2921         *)
2922    "report file system disk space usage",
2923    "\
2924 This command runs the C<df> command to report disk space used.
2925
2926 This command is mostly useful for interactive sessions.  It
2927 is I<not> intended that you try to parse the output string.
2928 Use C<statvfs> from programs.");
2929
2930   ("df_h", (RString "output", []), 126, [],
2931    [], (* XXX Tricky to test because it depends on the exact format
2932         * of the 'df' command and other imponderables.
2933         *)
2934    "report file system disk space usage (human readable)",
2935    "\
2936 This command runs the C<df -h> command to report disk space used
2937 in human-readable format.
2938
2939 This command is mostly useful for interactive sessions.  It
2940 is I<not> intended that you try to parse the output string.
2941 Use C<statvfs> from programs.");
2942
2943   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2944    [InitISOFS, Always, TestOutputInt (
2945       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2946    "estimate file space usage",
2947    "\
2948 This command runs the C<du -s> command to estimate file space
2949 usage for C<path>.
2950
2951 C<path> can be a file or a directory.  If C<path> is a directory
2952 then the estimate includes the contents of the directory and all
2953 subdirectories (recursively).
2954
2955 The result is the estimated size in I<kilobytes>
2956 (ie. units of 1024 bytes).");
2957
2958   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2959    [InitISOFS, Always, TestOutputList (
2960       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2961    "list files in an initrd",
2962    "\
2963 This command lists out files contained in an initrd.
2964
2965 The files are listed without any initial C</> character.  The
2966 files are listed in the order they appear (not necessarily
2967 alphabetical).  Directory names are listed as separate items.
2968
2969 Old Linux kernels (2.4 and earlier) used a compressed ext2
2970 filesystem as initrd.  We I<only> support the newer initramfs
2971 format (compressed cpio files).");
2972
2973   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2974    [],
2975    "mount a file using the loop device",
2976    "\
2977 This command lets you mount C<file> (a filesystem image
2978 in a file) on a mount point.  It is entirely equivalent to
2979 the command C<mount -o loop file mountpoint>.");
2980
2981   ("mkswap", (RErr, [Device "device"]), 130, [],
2982    [InitEmpty, Always, TestRun (
2983       [["part_disk"; "/dev/sda"; "mbr"];
2984        ["mkswap"; "/dev/sda1"]])],
2985    "create a swap partition",
2986    "\
2987 Create a swap partition on C<device>.");
2988
2989   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2990    [InitEmpty, Always, TestRun (
2991       [["part_disk"; "/dev/sda"; "mbr"];
2992        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2993    "create a swap partition with a label",
2994    "\
2995 Create a swap partition on C<device> with label C<label>.
2996
2997 Note that you cannot attach a swap label to a block device
2998 (eg. C</dev/sda>), just to a partition.  This appears to be
2999 a limitation of the kernel or swap tools.");
3000
3001   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3002    (let uuid = uuidgen () in
3003     [InitEmpty, Always, TestRun (
3004        [["part_disk"; "/dev/sda"; "mbr"];
3005         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3006    "create a swap partition with an explicit UUID",
3007    "\
3008 Create a swap partition on C<device> with UUID C<uuid>.");
3009
3010   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3011    [InitBasicFS, Always, TestOutputStruct (
3012       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3013        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3014        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3015     InitBasicFS, Always, TestOutputStruct (
3016       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3017        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3018    "make block, character or FIFO devices",
3019    "\
3020 This call creates block or character special devices, or
3021 named pipes (FIFOs).
3022
3023 The C<mode> parameter should be the mode, using the standard
3024 constants.  C<devmajor> and C<devminor> are the
3025 device major and minor numbers, only used when creating block
3026 and character special devices.
3027
3028 Note that, just like L<mknod(2)>, the mode must be bitwise
3029 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3030 just creates a regular file).  These constants are
3031 available in the standard Linux header files, or you can use
3032 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3033 which are wrappers around this command which bitwise OR
3034 in the appropriate constant for you.
3035
3036 The mode actually set is affected by the umask.");
3037
3038   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3039    [InitBasicFS, Always, TestOutputStruct (
3040       [["mkfifo"; "0o777"; "/node"];
3041        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3042    "make FIFO (named pipe)",
3043    "\
3044 This call creates a FIFO (named pipe) called C<path> with
3045 mode C<mode>.  It is just a convenient wrapper around
3046 C<guestfs_mknod>.
3047
3048 The mode actually set is affected by the umask.");
3049
3050   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3051    [InitBasicFS, Always, TestOutputStruct (
3052       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3053        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3054    "make block device node",
3055    "\
3056 This call creates a block device node called C<path> with
3057 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3058 It is just a convenient wrapper around C<guestfs_mknod>.
3059
3060 The mode actually set is affected by the umask.");
3061
3062   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3065        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3066    "make char device node",
3067    "\
3068 This call creates a char device node called C<path> with
3069 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3070 It is just a convenient wrapper around C<guestfs_mknod>.
3071
3072 The mode actually set is affected by the umask.");
3073
3074   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3075    [InitEmpty, Always, TestOutputInt (
3076       [["umask"; "0o22"]], 0o22)],
3077    "set file mode creation mask (umask)",
3078    "\
3079 This function sets the mask used for creating new files and
3080 device nodes to C<mask & 0777>.
3081
3082 Typical umask values would be C<022> which creates new files
3083 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3084 C<002> which creates new files with permissions like
3085 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3086
3087 The default umask is C<022>.  This is important because it
3088 means that directories and device nodes will be created with
3089 C<0644> or C<0755> mode even if you specify C<0777>.
3090
3091 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3092
3093 This call returns the previous umask.");
3094
3095   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3096    [],
3097    "read directories entries",
3098    "\
3099 This returns the list of directory entries in directory C<dir>.
3100
3101 All entries in the directory are returned, including C<.> and
3102 C<..>.  The entries are I<not> sorted, but returned in the same
3103 order as the underlying filesystem.
3104
3105 Also this call returns basic file type information about each
3106 file.  The C<ftyp> field will contain one of the following characters:
3107
3108 =over 4
3109
3110 =item 'b'
3111
3112 Block special
3113
3114 =item 'c'
3115
3116 Char special
3117
3118 =item 'd'
3119
3120 Directory
3121
3122 =item 'f'
3123
3124 FIFO (named pipe)
3125
3126 =item 'l'
3127
3128 Symbolic link
3129
3130 =item 'r'
3131
3132 Regular file
3133
3134 =item 's'
3135
3136 Socket
3137
3138 =item 'u'
3139
3140 Unknown file type
3141
3142 =item '?'
3143
3144 The L<readdir(3)> call returned a C<d_type> field with an
3145 unexpected value
3146
3147 =back
3148
3149 This function is primarily intended for use by programs.  To
3150 get a simple list of names, use C<guestfs_ls>.  To get a printable
3151 directory for human consumption, use C<guestfs_ll>.");
3152
3153   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3154    [],
3155    "create partitions on a block device",
3156    "\
3157 This is a simplified interface to the C<guestfs_sfdisk>
3158 command, where partition sizes are specified in megabytes
3159 only (rounded to the nearest cylinder) and you don't need
3160 to specify the cyls, heads and sectors parameters which
3161 were rarely if ever used anyway.
3162
3163 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3164 and C<guestfs_part_disk>");
3165
3166   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3167    [],
3168    "determine file type inside a compressed file",
3169    "\
3170 This command runs C<file> after first decompressing C<path>
3171 using C<method>.
3172
3173 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3174
3175 Since 1.0.63, use C<guestfs_file> instead which can now
3176 process compressed files.");
3177
3178   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3179    [],
3180    "list extended attributes of a file or directory",
3181    "\
3182 This call lists the extended attributes of the file or directory
3183 C<path>.
3184
3185 At the system call level, this is a combination of the
3186 L<listxattr(2)> and L<getxattr(2)> calls.
3187
3188 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3189
3190   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3191    [],
3192    "list extended attributes of a file or directory",
3193    "\
3194 This is the same as C<guestfs_getxattrs>, but if C<path>
3195 is a symbolic link, then it returns the extended attributes
3196 of the link itself.");
3197
3198   ("setxattr", (RErr, [String "xattr";
3199                        String "val"; Int "vallen"; (* will be BufferIn *)
3200                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3201    [],
3202    "set extended attribute of a file or directory",
3203    "\
3204 This call sets the extended attribute named C<xattr>
3205 of the file C<path> to the value C<val> (of length C<vallen>).
3206 The value is arbitrary 8 bit data.
3207
3208 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3209
3210   ("lsetxattr", (RErr, [String "xattr";
3211                         String "val"; Int "vallen"; (* will be BufferIn *)
3212                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3213    [],
3214    "set extended attribute of a file or directory",
3215    "\
3216 This is the same as C<guestfs_setxattr>, but if C<path>
3217 is a symbolic link, then it sets an extended attribute
3218 of the link itself.");
3219
3220   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3221    [],
3222    "remove extended attribute of a file or directory",
3223    "\
3224 This call removes the extended attribute named C<xattr>
3225 of the file C<path>.
3226
3227 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3228
3229   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3230    [],
3231    "remove extended attribute of a file or directory",
3232    "\
3233 This is the same as C<guestfs_removexattr>, but if C<path>
3234 is a symbolic link, then it removes an extended attribute
3235 of the link itself.");
3236
3237   ("mountpoints", (RHashtable "mps", []), 147, [],
3238    [],
3239    "show mountpoints",
3240    "\
3241 This call is similar to C<guestfs_mounts>.  That call returns
3242 a list of devices.  This one returns a hash table (map) of
3243 device name to directory where the device is mounted.");
3244
3245   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3246    (* This is a special case: while you would expect a parameter
3247     * of type "Pathname", that doesn't work, because it implies
3248     * NEED_ROOT in the generated calling code in stubs.c, and
3249     * this function cannot use NEED_ROOT.
3250     *)
3251    [],
3252    "create a mountpoint",
3253    "\
3254 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3255 specialized calls that can be used to create extra mountpoints
3256 before mounting the first filesystem.
3257
3258 These calls are I<only> necessary in some very limited circumstances,
3259 mainly the case where you want to mount a mix of unrelated and/or
3260 read-only filesystems together.
3261
3262 For example, live CDs often contain a \"Russian doll\" nest of
3263 filesystems, an ISO outer layer, with a squashfs image inside, with
3264 an ext2/3 image inside that.  You can unpack this as follows
3265 in guestfish:
3266
3267  add-ro Fedora-11-i686-Live.iso
3268  run
3269  mkmountpoint /cd
3270  mkmountpoint /squash
3271  mkmountpoint /ext3
3272  mount /dev/sda /cd
3273  mount-loop /cd/LiveOS/squashfs.img /squash
3274  mount-loop /squash/LiveOS/ext3fs.img /ext3
3275
3276 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3277
3278   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3279    [],
3280    "remove a mountpoint",
3281    "\
3282 This calls removes a mountpoint that was previously created
3283 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3284 for full details.");
3285
3286   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputBuffer (
3288       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3289     (* Test various near large, large and too large files (RHBZ#589039). *)
3290     InitBasicFS, Always, TestLastFail (
3291       [["touch"; "/a"];
3292        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3293        ["read_file"; "/a"]]);
3294     InitBasicFS, Always, TestLastFail (
3295       [["touch"; "/a"];
3296        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3297        ["read_file"; "/a"]]);
3298     InitBasicFS, Always, TestLastFail (
3299       [["touch"; "/a"];
3300        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3301        ["read_file"; "/a"]])],
3302    "read a file",
3303    "\
3304 This calls returns the contents of the file C<path> as a
3305 buffer.
3306
3307 Unlike C<guestfs_cat>, this function can correctly
3308 handle files that contain embedded ASCII NUL characters.
3309 However unlike C<guestfs_download>, this function is limited
3310 in the total size of file that can be handled.");
3311
3312   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3313    [InitISOFS, Always, TestOutputList (
3314       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3315     InitISOFS, Always, TestOutputList (
3316       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3317    "return lines matching a pattern",
3318    "\
3319 This calls the external C<grep> program and returns the
3320 matching lines.");
3321
3322   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3325    "return lines matching a pattern",
3326    "\
3327 This calls the external C<egrep> program and returns the
3328 matching lines.");
3329
3330   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3331    [InitISOFS, Always, TestOutputList (
3332       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<fgrep> program and returns the
3336 matching lines.");
3337
3338   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<grep -i> program and returns the
3344 matching lines.");
3345
3346   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<egrep -i> program and returns the
3352 matching lines.");
3353
3354   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<fgrep -i> program and returns the
3360 matching lines.");
3361
3362   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3363    [InitISOFS, Always, TestOutputList (
3364       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3365    "return lines matching a pattern",
3366    "\
3367 This calls the external C<zgrep> program and returns the
3368 matching lines.");
3369
3370   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3371    [InitISOFS, Always, TestOutputList (
3372       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<zegrep> program and returns the
3376 matching lines.");
3377
3378   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<zfgrep> program and returns the
3384 matching lines.");
3385
3386   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<zgrep -i> program and returns the
3392 matching lines.");
3393
3394   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<zegrep -i> program and returns the
3400 matching lines.");
3401
3402   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<zfgrep -i> program and returns the
3408 matching lines.");
3409
3410   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3411    [InitISOFS, Always, TestOutput (
3412       [["realpath"; "/../directory"]], "/directory")],
3413    "canonicalized absolute pathname",
3414    "\
3415 Return the canonicalized absolute pathname of C<path>.  The
3416 returned path has no C<.>, C<..> or symbolic link path elements.");
3417
3418   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3419    [InitBasicFS, Always, TestOutputStruct (
3420       [["touch"; "/a"];
3421        ["ln"; "/a"; "/b"];
3422        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3423    "create a hard link",
3424    "\
3425 This command creates a hard link using the C<ln> command.");
3426
3427   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3428    [InitBasicFS, Always, TestOutputStruct (
3429       [["touch"; "/a"];
3430        ["touch"; "/b"];
3431        ["ln_f"; "/a"; "/b"];
3432        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3433    "create a hard link",
3434    "\
3435 This command creates a hard link using the C<ln -f> command.
3436 The C<-f> option removes the link (C<linkname>) if it exists already.");
3437
3438   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3439    [InitBasicFS, Always, TestOutputStruct (
3440       [["touch"; "/a"];
3441        ["ln_s"; "a"; "/b"];
3442        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3443    "create a symbolic link",
3444    "\
3445 This command creates a symbolic link using the C<ln -s> command.");
3446
3447   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3448    [InitBasicFS, Always, TestOutput (
3449       [["mkdir_p"; "/a/b"];
3450        ["touch"; "/a/b/c"];
3451        ["ln_sf"; "../d"; "/a/b/c"];
3452        ["readlink"; "/a/b/c"]], "../d")],
3453    "create a symbolic link",
3454    "\
3455 This command creates a symbolic link using the C<ln -sf> command,
3456 The C<-f> option removes the link (C<linkname>) if it exists already.");
3457
3458   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3459    [] (* XXX tested above *),
3460    "read the target of a symbolic link",
3461    "\
3462 This command reads the target of a symbolic link.");
3463
3464   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3465    [InitBasicFS, Always, TestOutputStruct (
3466       [["fallocate"; "/a"; "1000000"];
3467        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3468    "preallocate a file in the guest filesystem",
3469    "\
3470 This command preallocates a file (containing zero bytes) named
3471 C<path> of size C<len> bytes.  If the file exists already, it
3472 is overwritten.
3473
3474 Do not confuse this with the guestfish-specific
3475 C<alloc> command which allocates a file in the host and
3476 attaches it as a device.");
3477
3478   ("swapon_device", (RErr, [Device "device"]), 170, [],
3479    [InitPartition, Always, TestRun (
3480       [["mkswap"; "/dev/sda1"];
3481        ["swapon_device"; "/dev/sda1"];
3482        ["swapoff_device"; "/dev/sda1"]])],
3483    "enable swap on device",
3484    "\
3485 This command enables the libguestfs appliance to use the
3486 swap device or partition named C<device>.  The increased
3487 memory is made available for all commands, for example
3488 those run using C<guestfs_command> or C<guestfs_sh>.
3489
3490 Note that you should not swap to existing guest swap
3491 partitions unless you know what you are doing.  They may
3492 contain hibernation information, or other information that
3493 the guest doesn't want you to trash.  You also risk leaking
3494 information about the host to the guest this way.  Instead,
3495 attach a new host device to the guest and swap on that.");
3496
3497   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3498    [], (* XXX tested by swapon_device *)
3499    "disable swap on device",
3500    "\
3501 This command disables the libguestfs appliance swap
3502 device or partition named C<device>.
3503 See C<guestfs_swapon_device>.");
3504
3505   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3506    [InitBasicFS, Always, TestRun (
3507       [["fallocate"; "/swap"; "8388608"];
3508        ["mkswap_file"; "/swap"];
3509        ["swapon_file"; "/swap"];
3510        ["swapoff_file"; "/swap"]])],
3511    "enable swap on file",
3512    "\
3513 This command enables swap to a file.
3514 See C<guestfs_swapon_device> for other notes.");
3515
3516   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3517    [], (* XXX tested by swapon_file *)
3518    "disable swap on file",
3519    "\
3520 This command disables the libguestfs appliance swap on file.");
3521
3522   ("swapon_label", (RErr, [String "label"]), 174, [],
3523    [InitEmpty, Always, TestRun (
3524       [["part_disk"; "/dev/sdb"; "mbr"];
3525        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3526        ["swapon_label"; "swapit"];
3527        ["swapoff_label"; "swapit"];
3528        ["zero"; "/dev/sdb"];
3529        ["blockdev_rereadpt"; "/dev/sdb"]])],
3530    "enable swap on labeled swap partition",
3531    "\
3532 This command enables swap to a labeled swap partition.
3533 See C<guestfs_swapon_device> for other notes.");
3534
3535   ("swapoff_label", (RErr, [String "label"]), 175, [],
3536    [], (* XXX tested by swapon_label *)
3537    "disable swap on labeled swap partition",
3538    "\
3539 This command disables the libguestfs appliance swap on
3540 labeled swap partition.");
3541
3542   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3543    (let uuid = uuidgen () in
3544     [InitEmpty, Always, TestRun (
3545        [["mkswap_U"; uuid; "/dev/sdb"];
3546         ["swapon_uuid"; uuid];
3547         ["swapoff_uuid"; uuid]])]),
3548    "enable swap on swap partition by UUID",
3549    "\
3550 This command enables swap to a swap partition with the given UUID.
3551 See C<guestfs_swapon_device> for other notes.");
3552
3553   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3554    [], (* XXX tested by swapon_uuid *)
3555    "disable swap on swap partition by UUID",
3556    "\
3557 This command disables the libguestfs appliance swap partition
3558 with the given UUID.");
3559
3560   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3561    [InitBasicFS, Always, TestRun (
3562       [["fallocate"; "/swap"; "8388608"];
3563        ["mkswap_file"; "/swap"]])],
3564    "create a swap file",
3565    "\
3566 Create a swap file.
3567
3568 This command just writes a swap file signature to an existing
3569 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3570
3571   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3572    [InitISOFS, Always, TestRun (
3573       [["inotify_init"; "0"]])],
3574    "create an inotify handle",
3575    "\
3576 This command creates a new inotify handle.
3577 The inotify subsystem can be used to notify events which happen to
3578 objects in the guest filesystem.
3579
3580 C<maxevents> is the maximum number of events which will be
3581 queued up between calls to C<guestfs_inotify_read> or
3582 C<guestfs_inotify_files>.
3583 If this is passed as C<0>, then the kernel (or previously set)
3584 default is used.  For Linux 2.6.29 the default was 16384 events.
3585 Beyond this limit, the kernel throws away events, but records
3586 the fact that it threw them away by setting a flag
3587 C<IN_Q_OVERFLOW> in the returned structure list (see
3588 C<guestfs_inotify_read>).
3589
3590 Before any events are generated, you have to add some
3591 watches to the internal watch list.  See:
3592 C<guestfs_inotify_add_watch>,
3593 C<guestfs_inotify_rm_watch> and
3594 C<guestfs_inotify_watch_all>.
3595
3596 Queued up events should be read periodically by calling
3597 C<guestfs_inotify_read>
3598 (or C<guestfs_inotify_files> which is just a helpful
3599 wrapper around C<guestfs_inotify_read>).  If you don't
3600 read the events out often enough then you risk the internal
3601 queue overflowing.
3602
3603 The handle should be closed after use by calling
3604 C<guestfs_inotify_close>.  This also removes any
3605 watches automatically.
3606
3607 See also L<inotify(7)> for an overview of the inotify interface
3608 as exposed by the Linux kernel, which is roughly what we expose
3609 via libguestfs.  Note that there is one global inotify handle
3610 per libguestfs instance.");
3611
3612   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3613    [InitBasicFS, Always, TestOutputList (
3614       [["inotify_init"; "0"];
3615        ["inotify_add_watch"; "/"; "1073741823"];
3616        ["touch"; "/a"];
3617        ["touch"; "/b"];
3618        ["inotify_files"]], ["a"; "b"])],
3619    "add an inotify watch",
3620    "\
3621 Watch C<path> for the events listed in C<mask>.
3622
3623 Note that if C<path> is a directory then events within that
3624 directory are watched, but this does I<not> happen recursively
3625 (in subdirectories).
3626
3627 Note for non-C or non-Linux callers: the inotify events are
3628 defined by the Linux kernel ABI and are listed in
3629 C</usr/include/sys/inotify.h>.");
3630
3631   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3632    [],
3633    "remove an inotify watch",
3634    "\
3635 Remove a previously defined inotify watch.
3636 See C<guestfs_inotify_add_watch>.");
3637
3638   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3639    [],
3640    "return list of inotify events",
3641    "\
3642 Return the complete queue of events that have happened
3643 since the previous read call.
3644
3645 If no events have happened, this returns an empty list.
3646
3647 I<Note>: In order to make sure that all events have been
3648 read, you must call this function repeatedly until it
3649 returns an empty list.  The reason is that the call will
3650 read events up to the maximum appliance-to-host message
3651 size and leave remaining events in the queue.");
3652
3653   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3654    [],
3655    "return list of watched files that had events",
3656    "\
3657 This function is a helpful wrapper around C<guestfs_inotify_read>
3658 which just returns a list of pathnames of objects that were
3659 touched.  The returned pathnames are sorted and deduplicated.");
3660
3661   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3662    [],
3663    "close the inotify handle",
3664    "\
3665 This closes the inotify handle which was previously
3666 opened by inotify_init.  It removes all watches, throws
3667 away any pending events, and deallocates all resources.");
3668
3669   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3670    [],
3671    "set SELinux security context",
3672    "\
3673 This sets the SELinux security context of the daemon
3674 to the string C<context>.
3675
3676 See the documentation about SELINUX in L<guestfs(3)>.");
3677
3678   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3679    [],
3680    "get SELinux security context",
3681    "\
3682 This gets the SELinux security context of the daemon.
3683
3684 See the documentation about SELINUX in L<guestfs(3)>,
3685 and C<guestfs_setcon>");
3686
3687   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3688    [InitEmpty, Always, TestOutput (
3689       [["part_disk"; "/dev/sda"; "mbr"];
3690        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3691        ["mount_options"; ""; "/dev/sda1"; "/"];
3692        ["write_file"; "/new"; "new file contents"; "0"];
3693        ["cat"; "/new"]], "new file contents")],
3694    "make a filesystem with block size",
3695    "\
3696 This call is similar to C<guestfs_mkfs>, but it allows you to
3697 control the block size of the resulting filesystem.  Supported
3698 block sizes depend on the filesystem type, but typically they
3699 are C<1024>, C<2048> or C<4096> only.");
3700
3701   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3704        ["mke2journal"; "4096"; "/dev/sda1"];
3705        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3706        ["mount_options"; ""; "/dev/sda2"; "/"];
3707        ["write_file"; "/new"; "new file contents"; "0"];
3708        ["cat"; "/new"]], "new file contents")],
3709    "make ext2/3/4 external journal",
3710    "\
3711 This creates an ext2 external journal on C<device>.  It is equivalent
3712 to the command:
3713
3714  mke2fs -O journal_dev -b blocksize device");
3715
3716   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3717    [InitEmpty, Always, TestOutput (
3718       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3719        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3720        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3721        ["mount_options"; ""; "/dev/sda2"; "/"];
3722        ["write_file"; "/new"; "new file contents"; "0"];
3723        ["cat"; "/new"]], "new file contents")],
3724    "make ext2/3/4 external journal with label",
3725    "\
3726 This creates an ext2 external journal on C<device> with label C<label>.");
3727
3728   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3729    (let uuid = uuidgen () in
3730     [InitEmpty, Always, TestOutput (
3731        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3732         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3733         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3734         ["mount_options"; ""; "/dev/sda2"; "/"];
3735         ["write_file"; "/new"; "new file contents"; "0"];
3736         ["cat"; "/new"]], "new file contents")]),
3737    "make ext2/3/4 external journal with UUID",
3738    "\
3739 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3740
3741   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3742    [],
3743    "make ext2/3/4 filesystem with external journal",
3744    "\
3745 This creates an ext2/3/4 filesystem on C<device> with
3746 an external journal on C<journal>.  It is equivalent
3747 to the command:
3748
3749  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3750
3751 See also C<guestfs_mke2journal>.");
3752
3753   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3754    [],
3755    "make ext2/3/4 filesystem with external journal",
3756    "\
3757 This creates an ext2/3/4 filesystem on C<device> with
3758 an external journal on the journal labeled C<label>.
3759
3760 See also C<guestfs_mke2journal_L>.");
3761
3762   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3763    [],
3764    "make ext2/3/4 filesystem with external journal",
3765    "\
3766 This creates an ext2/3/4 filesystem on C<device> with
3767 an external journal on the journal with UUID C<uuid>.
3768
3769 See also C<guestfs_mke2journal_U>.");
3770
3771   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3772    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3773    "load a kernel module",
3774    "\
3775 This loads a kernel module in the appliance.
3776
3777 The kernel module must have been whitelisted when libguestfs
3778 was built (see C<appliance/kmod.whitelist.in> in the source).");
3779
3780   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3781    [InitNone, Always, TestOutput (
3782       [["echo_daemon"; "This is a test"]], "This is a test"
3783     )],
3784    "echo arguments back to the client",
3785    "\
3786 This command concatenates the list of C<words> passed with single spaces
3787 between them and returns the resulting string.
3788
3789 You can use this command to test the connection through to the daemon.
3790
3791 See also C<guestfs_ping_daemon>.");
3792
3793   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3794    [], (* There is a regression test for this. *)
3795    "find all files and directories, returning NUL-separated list",
3796    "\
3797 This command lists out all files and directories, recursively,
3798 starting at C<directory>, placing the resulting list in the
3799 external file called C<files>.
3800
3801 This command works the same way as C<guestfs_find> with the
3802 following exceptions:
3803
3804 =over 4
3805
3806 =item *
3807
3808 The resulting list is written to an external file.
3809
3810 =item *
3811
3812 Items (filenames) in the result are separated
3813 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3814
3815 =item *
3816
3817 This command is not limited in the number of names that it
3818 can return.
3819
3820 =item *
3821
3822 The result list is not sorted.
3823
3824 =back");
3825
3826   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3827    [InitISOFS, Always, TestOutput (
3828       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3829     InitISOFS, Always, TestOutput (
3830       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3831     InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3833     InitISOFS, Always, TestLastFail (
3834       [["case_sensitive_path"; "/Known-1/"]]);
3835     InitBasicFS, Always, TestOutput (
3836       [["mkdir"; "/a"];
3837        ["mkdir"; "/a/bbb"];
3838        ["touch"; "/a/bbb/c"];
3839        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3840     InitBasicFS, Always, TestOutput (
3841       [["mkdir"; "/a"];
3842        ["mkdir"; "/a/bbb"];
3843        ["touch"; "/a/bbb/c"];
3844        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3845     InitBasicFS, Always, TestLastFail (
3846       [["mkdir"; "/a"];
3847        ["mkdir"; "/a/bbb"];
3848        ["touch"; "/a/bbb/c"];
3849        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3850    "return true path on case-insensitive filesystem",
3851    "\
3852 This can be used to resolve case insensitive paths on
3853 a filesystem which is case sensitive.  The use case is
3854 to resolve paths which you have read from Windows configuration
3855 files or the Windows Registry, to the true path.
3856
3857 The command handles a peculiarity of the Linux ntfs-3g
3858 filesystem driver (and probably others), which is that although
3859 the underlying filesystem is case-insensitive, the driver
3860 exports the filesystem to Linux as case-sensitive.
3861
3862 One consequence of this is that special directories such
3863 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3864 (or other things) depending on the precise details of how
3865 they were created.  In Windows itself this would not be
3866 a problem.
3867
3868 Bug or feature?  You decide:
3869 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3870
3871 This function resolves the true case of each element in the
3872 path and returns the case-sensitive path.
3873
3874 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3875 might return C<\"/WINDOWS/system32\"> (the exact return value
3876 would depend on details of how the directories were originally
3877 created under Windows).
3878
3879 I<Note>:
3880 This function does not handle drive names, backslashes etc.
3881
3882 See also C<guestfs_realpath>.");
3883
3884   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3885    [InitBasicFS, Always, TestOutput (
3886       [["vfs_type"; "/dev/sda1"]], "ext2")],
3887    "get the Linux VFS type corresponding to a mounted device",
3888    "\
3889 This command gets the block device type corresponding to
3890 a mounted device called C<device>.
3891
3892 Usually the result is the name of the Linux VFS module that
3893 is used to mount this device (probably determined automatically
3894 if you used the C<guestfs_mount> call).");
3895
3896   ("truncate", (RErr, [Pathname "path"]), 199, [],
3897    [InitBasicFS, Always, TestOutputStruct (
3898       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3899        ["truncate"; "/test"];
3900        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3901    "truncate a file to zero size",
3902    "\
3903 This command truncates C<path> to a zero-length file.  The
3904 file must exist already.");
3905
3906   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3907    [InitBasicFS, Always, TestOutputStruct (
3908       [["touch"; "/test"];
3909        ["truncate_size"; "/test"; "1000"];
3910        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3911    "truncate a file to a particular size",
3912    "\
3913 This command truncates C<path> to size C<size> bytes.  The file
3914 must exist already.
3915
3916 If the current file size is less than C<size> then
3917 the file is extended to the required size with zero bytes.
3918 This creates a sparse file (ie. disk blocks are not allocated
3919 for the file until you write to it).  To create a non-sparse
3920 file of zeroes, use C<guestfs_fallocate64> instead.");
3921
3922   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3923    [InitBasicFS, Always, TestOutputStruct (
3924       [["touch"; "/test"];
3925        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3926        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3927    "set timestamp of a file with nanosecond precision",
3928    "\
3929 This command sets the timestamps of a file with nanosecond
3930 precision.
3931
3932 C<atsecs, atnsecs> are the last access time (atime) in secs and
3933 nanoseconds from the epoch.
3934
3935 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3936 secs and nanoseconds from the epoch.
3937
3938 If the C<*nsecs> field contains the special value C<-1> then
3939 the corresponding timestamp is set to the current time.  (The
3940 C<*secs> field is ignored in this case).
3941
3942 If the C<*nsecs> field contains the special value C<-2> then
3943 the corresponding timestamp is left unchanged.  (The
3944 C<*secs> field is ignored in this case).");
3945
3946   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3947    [InitBasicFS, Always, TestOutputStruct (
3948       [["mkdir_mode"; "/test"; "0o111"];
3949        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3950    "create a directory with a particular mode",
3951    "\
3952 This command creates a directory, setting the initial permissions
3953 of the directory to C<mode>.
3954
3955 For common Linux filesystems, the actual mode which is set will
3956 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3957 interpret the mode in other ways.
3958
3959 See also C<guestfs_mkdir>, C<guestfs_umask>");
3960
3961   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3962    [], (* XXX *)
3963    "change file owner and group",
3964    "\
3965 Change the file owner to C<owner> and group to C<group>.
3966 This is like C<guestfs_chown> but if C<path> is a symlink then
3967 the link itself is changed, not the target.
3968
3969 Only numeric uid and gid are supported.  If you want to use
3970 names, you will need to locate and parse the password file
3971 yourself (Augeas support makes this relatively easy).");
3972
3973   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3974    [], (* XXX *)
3975    "lstat on multiple files",
3976    "\
3977 This call allows you to perform the C<guestfs_lstat> operation
3978 on multiple files, where all files are in the directory C<path>.
3979 C<names> is the list of files from this directory.
3980
3981 On return you get a list of stat structs, with a one-to-one
3982 correspondence to the C<names> list.  If any name did not exist
3983 or could not be lstat'd, then the C<ino> field of that structure
3984 is set to C<-1>.
3985
3986 This call is intended for programs that want to efficiently
3987 list a directory contents without making many round-trips.
3988 See also C<guestfs_lxattrlist> for a similarly efficient call
3989 for getting extended attributes.  Very long directory listings
3990 might cause the protocol message size to be exceeded, causing
3991 this call to fail.  The caller must split up such requests
3992 into smaller groups of names.");
3993
3994   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3995    [], (* XXX *)
3996    "lgetxattr on multiple files",
3997    "\
3998 This call allows you to get the extended attributes
3999 of multiple files, where all files are in the directory C<path>.
4000 C<names> is the list of files from this directory.
4001
4002 On return you get a flat list of xattr structs which must be
4003 interpreted sequentially.  The first xattr struct always has a zero-length
4004 C<attrname>.  C<attrval> in this struct is zero-length
4005 to indicate there was an error doing C<lgetxattr> for this
4006 file, I<or> is a C string which is a decimal number
4007 (the number of following attributes for this file, which could
4008 be C<\"0\">).  Then after the first xattr struct are the
4009 zero or more attributes for the first named file.
4010 This repeats for the second and subsequent files.
4011
4012 This call is intended for programs that want to efficiently
4013 list a directory contents without making many round-trips.
4014 See also C<guestfs_lstatlist> for a similarly efficient call
4015 for getting standard stats.  Very long directory listings
4016 might cause the protocol message size to be exceeded, causing
4017 this call to fail.  The caller must split up such requests
4018 into smaller groups of names.");
4019
4020   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4021    [], (* XXX *)
4022    "readlink on multiple files",
4023    "\
4024 This call allows you to do a C<readlink> operation
4025 on multiple files, where all files are in the directory C<path>.
4026 C<names> is the list of files from this directory.
4027
4028 On return you get a list of strings, with a one-to-one
4029 correspondence to the C<names> list.  Each string is the
4030 value of the symbolic link.
4031
4032 If the C<readlink(2)> operation fails on any name, then
4033 the corresponding result string is the empty string C<\"\">.
4034 However the whole operation is completed even if there
4035 were C<readlink(2)> errors, and so you can call this
4036 function with names where you don't know if they are
4037 symbolic links already (albeit slightly less efficient).
4038
4039 This call is intended for programs that want to efficiently
4040 list a directory contents without making many round-trips.
4041 Very long directory listings might cause the protocol
4042 message size to be exceeded, causing
4043 this call to fail.  The caller must split up such requests
4044 into smaller groups of names.");
4045
4046   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4047    [InitISOFS, Always, TestOutputBuffer (
4048       [["pread"; "/known-4"; "1"; "3"]], "\n");
4049     InitISOFS, Always, TestOutputBuffer (
4050       [["pread"; "/empty"; "0"; "100"]], "")],
4051    "read part of a file",
4052    "\
4053 This command lets you read part of a file.  It reads C<count>
4054 bytes of the file, starting at C<offset>, from file C<path>.
4055
4056 This may read fewer bytes than requested.  For further details
4057 see the L<pread(2)> system call.");
4058
4059   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4060    [InitEmpty, Always, TestRun (
4061       [["part_init"; "/dev/sda"; "gpt"]])],
4062    "create an empty partition table",
4063    "\
4064 This creates an empty partition table on C<device> of one of the
4065 partition types listed below.  Usually C<parttype> should be
4066 either C<msdos> or C<gpt> (for large disks).
4067
4068 Initially there are no partitions.  Following this, you should
4069 call C<guestfs_part_add> for each partition required.
4070
4071 Possible values for C<parttype> are:
4072
4073 =over 4
4074
4075 =item B<efi> | B<gpt>
4076
4077 Intel EFI / GPT partition table.
4078
4079 This is recommended for >= 2 TB partitions that will be accessed
4080 from Linux and Intel-based Mac OS X.  It also has limited backwards
4081 compatibility with the C<mbr> format.
4082
4083 =item B<mbr> | B<msdos>
4084
4085 The standard PC \"Master Boot Record\" (MBR) format used
4086 by MS-DOS and Windows.  This partition type will B<only> work
4087 for device sizes up to 2 TB.  For large disks we recommend
4088 using C<gpt>.
4089
4090 =back
4091
4092 Other partition table types that may work but are not
4093 supported include:
4094
4095 =over 4
4096
4097 =item B<aix>
4098
4099 AIX disk labels.
4100
4101 =item B<amiga> | B<rdb>
4102
4103 Amiga \"Rigid Disk Block\" format.
4104
4105 =item B<bsd>
4106
4107 BSD disk labels.
4108
4109 =item B<dasd>
4110
4111 DASD, used on IBM mainframes.
4112
4113 =item B<dvh>
4114
4115 MIPS/SGI volumes.
4116
4117 =item B<mac>
4118
4119 Old Mac partition format.  Modern Macs use C<gpt>.
4120
4121 =item B<pc98>
4122
4123 NEC PC-98 format, common in Japan apparently.
4124
4125 =item B<sun>
4126
4127 Sun disk labels.
4128
4129 =back");
4130
4131   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4132    [InitEmpty, Always, TestRun (
4133       [["part_init"; "/dev/sda"; "mbr"];
4134        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4135     InitEmpty, Always, TestRun (
4136       [["part_init"; "/dev/sda"; "gpt"];
4137        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4138        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4139     InitEmpty, Always, TestRun (
4140       [["part_init"; "/dev/sda"; "mbr"];
4141        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4142        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4143        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4144        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4145    "add a partition to the device",
4146    "\
4147 This command adds a partition to C<device>.  If there is no partition
4148 table on the device, call C<guestfs_part_init> first.
4149
4150 The C<prlogex> parameter is the type of partition.  Normally you
4151 should pass C<p> or C<primary> here, but MBR partition tables also
4152 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4153 types.
4154
4155 C<startsect> and C<endsect> are the start and end of the partition
4156 in I<sectors>.  C<endsect> may be negative, which means it counts
4157 backwards from the end of the disk (C<-1> is the last sector).
4158
4159 Creating a partition which covers the whole disk is not so easy.
4160 Use C<guestfs_part_disk> to do that.");
4161
4162   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4163    [InitEmpty, Always, TestRun (
4164       [["part_disk"; "/dev/sda"; "mbr"]]);
4165     InitEmpty, Always, TestRun (
4166       [["part_disk"; "/dev/sda"; "gpt"]])],
4167    "partition whole disk with a single primary partition",
4168    "\
4169 This command is simply a combination of C<guestfs_part_init>
4170 followed by C<guestfs_part_add> to create a single primary partition
4171 covering the whole disk.
4172
4173 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4174 but other possible values are described in C<guestfs_part_init>.");
4175
4176   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4177    [InitEmpty, Always, TestRun (
4178       [["part_disk"; "/dev/sda"; "mbr"];
4179        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4180    "make a partition bootable",
4181    "\
4182 This sets the bootable flag on partition numbered C<partnum> on
4183 device C<device>.  Note that partitions are numbered from 1.
4184
4185 The bootable flag is used by some operating systems (notably
4186 Windows) to determine which partition to boot from.  It is by
4187 no means universally recognized.");
4188
4189   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4190    [InitEmpty, Always, TestRun (
4191       [["part_disk"; "/dev/sda"; "gpt"];
4192        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4193    "set partition name",
4194    "\
4195 This sets the partition name on partition numbered C<partnum> on
4196 device C<device>.  Note that partitions are numbered from 1.
4197
4198 The partition name can only be set on certain types of partition
4199 table.  This works on C<gpt> but not on C<mbr> partitions.");
4200
4201   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4202    [], (* XXX Add a regression test for this. *)
4203    "list partitions on a device",
4204    "\
4205 This command parses the partition table on C<device> and
4206 returns the list of partitions found.
4207
4208 The fields in the returned structure are:
4209
4210 =over 4
4211
4212 =item B<part_num>
4213
4214 Partition number, counting from 1.
4215
4216 =item B<part_start>
4217
4218 Start of the partition I<in bytes>.  To get sectors you have to
4219 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4220
4221 =item B<part_end>
4222
4223 End of the partition in bytes.
4224
4225 =item B<part_size>
4226
4227 Size of the partition in bytes.
4228
4229 =back");
4230
4231   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4232    [InitEmpty, Always, TestOutput (
4233       [["part_disk"; "/dev/sda"; "gpt"];
4234        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4235    "get the partition table type",
4236    "\
4237 This command examines the partition table on C<device> and
4238 returns the partition table type (format) being used.
4239
4240 Common return values include: C<msdos> (a DOS/Windows style MBR
4241 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4242 values are possible, although unusual.  See C<guestfs_part_init>
4243 for a full list.");
4244
4245   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4246    [InitBasicFS, Always, TestOutputBuffer (
4247       [["fill"; "0x63"; "10"; "/test"];
4248        ["read_file"; "/test"]], "cccccccccc")],
4249    "fill a file with octets",
4250    "\
4251 This command creates a new file called C<path>.  The initial
4252 content of the file is C<len> octets of C<c>, where C<c>
4253 must be a number in the range C<[0..255]>.
4254
4255 To fill a file with zero bytes (sparsely), it is
4256 much more efficient to use C<guestfs_truncate_size>.");
4257
4258   ("available", (RErr, [StringList "groups"]), 216, [],
4259    [InitNone, Always, TestRun [["available"; ""]]],
4260    "test availability of some parts of the API",
4261    "\
4262 This command is used to check the availability of some
4263 groups of functionality in the appliance, which not all builds of
4264 the libguestfs appliance will be able to provide.
4265
4266 The libguestfs groups, and the functions that those
4267 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4268
4269 The argument C<groups> is a list of group names, eg:
4270 C<[\"inotify\", \"augeas\"]> would check for the availability of
4271 the Linux inotify functions and Augeas (configuration file
4272 editing) functions.
4273
4274 The command returns no error if I<all> requested groups are available.
4275
4276 It fails with an error if one or more of the requested
4277 groups is unavailable in the appliance.
4278
4279 If an unknown group name is included in the
4280 list of groups then an error is always returned.
4281
4282 I<Notes:>
4283
4284 =over 4
4285
4286 =item *
4287
4288 You must call C<guestfs_launch> before calling this function.
4289
4290 The reason is because we don't know what groups are
4291 supported by the appliance/daemon until it is running and can
4292 be queried.
4293
4294 =item *
4295
4296 If a group of functions is available, this does not necessarily
4297 mean that they will work.  You still have to check for errors
4298 when calling individual API functions even if they are
4299 available.
4300
4301 =item *
4302
4303 It is usually the job of distro packagers to build
4304 complete functionality into the libguestfs appliance.
4305 Upstream libguestfs, if built from source with all
4306 requirements satisfied, will support everything.
4307
4308 =item *
4309
4310 This call was added in version C<1.0.80>.  In previous
4311 versions of libguestfs all you could do would be to speculatively
4312 execute a command to find out if the daemon implemented it.
4313 See also C<guestfs_version>.
4314
4315 =back");
4316
4317   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4318    [InitBasicFS, Always, TestOutputBuffer (
4319       [["write_file"; "/src"; "hello, world"; "0"];
4320        ["dd"; "/src"; "/dest"];
4321        ["read_file"; "/dest"]], "hello, world")],
4322    "copy from source to destination using dd",
4323    "\
4324 This command copies from one source device or file C<src>
4325 to another destination device or file C<dest>.  Normally you
4326 would use this to copy to or from a device or partition, for
4327 example to duplicate a filesystem.
4328
4329 If the destination is a device, it must be as large or larger
4330 than the source file or device, otherwise the copy will fail.
4331 This command cannot do partial copies (see C<guestfs_copy_size>).");
4332
4333   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4334    [InitBasicFS, Always, TestOutputInt (
4335       [["write_file"; "/file"; "hello, world"; "0"];
4336        ["filesize"; "/file"]], 12)],
4337    "return the size of the file in bytes",
4338    "\
4339 This command returns the size of C<file> in bytes.
4340
4341 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4342 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4343 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4344
4345   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4346    [InitBasicFSonLVM, Always, TestOutputList (
4347       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4348        ["lvs"]], ["/dev/VG/LV2"])],
4349    "rename an LVM logical volume",
4350    "\
4351 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4352
4353   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4354    [InitBasicFSonLVM, Always, TestOutputList (
4355       [["umount"; "/"];
4356        ["vg_activate"; "false"; "VG"];
4357        ["vgrename"; "VG"; "VG2"];
4358        ["vg_activate"; "true"; "VG2"];
4359        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4360        ["vgs"]], ["VG2"])],
4361    "rename an LVM volume group",
4362    "\
4363 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4364
4365   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4366    [InitISOFS, Always, TestOutputBuffer (
4367       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4368    "list the contents of a single file in an initrd",
4369    "\
4370 This command unpacks the file C<filename> from the initrd file
4371 called C<initrdpath>.  The filename must be given I<without> the
4372 initial C</> character.
4373
4374 For example, in guestfish you could use the following command
4375 to examine the boot script (usually called C</init>)
4376 contained in a Linux initrd or initramfs image:
4377
4378  initrd-cat /boot/initrd-<version>.img init
4379
4380 See also C<guestfs_initrd_list>.");
4381
4382   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4383    [],
4384    "get the UUID of a physical volume",
4385    "\
4386 This command returns the UUID of the LVM PV C<device>.");
4387
4388   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4389    [],
4390    "get the UUID of a volume group",
4391    "\
4392 This command returns the UUID of the LVM VG named C<vgname>.");
4393
4394   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4395    [],
4396    "get the UUID of a logical volume",
4397    "\
4398 This command returns the UUID of the LVM LV C<device>.");
4399
4400   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4401    [],
4402    "get the PV UUIDs containing the volume group",
4403    "\
4404 Given a VG called C<vgname>, this returns the UUIDs of all
4405 the physical volumes that this volume group resides on.
4406
4407 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4408 calls to associate physical volumes and volume groups.
4409
4410 See also C<guestfs_vglvuuids>.");
4411
4412   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4413    [],
4414    "get the LV UUIDs of all LVs in the volume group",
4415    "\
4416 Given a VG called C<vgname>, this returns the UUIDs of all
4417 the logical volumes created in this volume group.
4418
4419 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4420 calls to associate logical volumes and volume groups.
4421
4422 See also C<guestfs_vgpvuuids>.");
4423
4424   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4425    [InitBasicFS, Always, TestOutputBuffer (
4426       [["write_file"; "/src"; "hello, world"; "0"];
4427        ["copy_size"; "/src"; "/dest"; "5"];
4428        ["read_file"; "/dest"]], "hello")],
4429    "copy size bytes from source to destination using dd",
4430    "\
4431 This command copies exactly C<size> bytes from one source device
4432 or file C<src> to another destination device or file C<dest>.
4433
4434 Note this will fail if the source is too short or if the destination
4435 is not large enough.");
4436
4437   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4438    [InitEmpty, Always, TestRun (
4439       [["part_init"; "/dev/sda"; "mbr"];
4440        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4441        ["part_del"; "/dev/sda"; "1"]])],
4442    "delete a partition",
4443    "\
4444 This command deletes the partition numbered C<partnum> on C<device>.
4445
4446 Note that in the case of MBR partitioning, deleting an
4447 extended partition also deletes any logical partitions
4448 it contains.");
4449
4450   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4451    [InitEmpty, Always, TestOutputTrue (
4452       [["part_init"; "/dev/sda"; "mbr"];
4453        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4454        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4455        ["part_get_bootable"; "/dev/sda"; "1"]])],
4456    "return true if a partition is bootable",
4457    "\
4458 This command returns true if the partition C<partnum> on
4459 C<device> has the bootable flag set.
4460
4461 See also C<guestfs_part_set_bootable>.");
4462
4463   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4464    [InitEmpty, Always, TestOutputInt (
4465       [["part_init"; "/dev/sda"; "mbr"];
4466        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4467        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4468        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4469    "get the MBR type byte (ID byte) from a partition",
4470    "\
4471 Returns the MBR type byte (also known as the ID byte) from
4472 the numbered partition C<partnum>.
4473
4474 Note that only MBR (old DOS-style) partitions have type bytes.
4475 You will get undefined results for other partition table
4476 types (see C<guestfs_part_get_parttype>).");
4477
4478   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4479    [], (* tested by part_get_mbr_id *)
4480    "set the MBR type byte (ID byte) of a partition",
4481    "\
4482 Sets the MBR type byte (also known as the ID byte) of
4483 the numbered partition C<partnum> to C<idbyte>.  Note
4484 that the type bytes quoted in most documentation are
4485 in fact hexadecimal numbers, but usually documented
4486 without any leading \"0x\" which might be confusing.
4487
4488 Note that only MBR (old DOS-style) partitions have type bytes.
4489 You will get undefined results for other partition table
4490 types (see C<guestfs_part_get_parttype>).");
4491
4492 ]
4493
4494 let all_functions = non_daemon_functions @ daemon_functions
4495
4496 (* In some places we want the functions to be displayed sorted
4497  * alphabetically, so this is useful:
4498  *)
4499 let all_functions_sorted =
4500   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4501                compare n1 n2) all_functions
4502
4503 (* Field types for structures. *)
4504 type field =
4505   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4506   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4507   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4508   | FUInt32
4509   | FInt32
4510   | FUInt64
4511   | FInt64
4512   | FBytes                      (* Any int measure that counts bytes. *)
4513   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4514   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4515
4516 (* Because we generate extra parsing code for LVM command line tools,
4517  * we have to pull out the LVM columns separately here.
4518  *)
4519 let lvm_pv_cols = [
4520   "pv_name", FString;
4521   "pv_uuid", FUUID;
4522   "pv_fmt", FString;
4523   "pv_size", FBytes;
4524   "dev_size", FBytes;
4525   "pv_free", FBytes;
4526   "pv_used", FBytes;
4527   "pv_attr", FString (* XXX *);
4528   "pv_pe_count", FInt64;
4529   "pv_pe_alloc_count", FInt64;
4530   "pv_tags", FString;
4531   "pe_start", FBytes;
4532   "pv_mda_count", FInt64;
4533   "pv_mda_free", FBytes;
4534   (* Not in Fedora 10:
4535      "pv_mda_size", FBytes;
4536   *)
4537 ]
4538 let lvm_vg_cols = [
4539   "vg_name", FString;
4540   "vg_uuid", FUUID;
4541   "vg_fmt", FString;
4542   "vg_attr", FString (* XXX *);
4543   "vg_size", FBytes;
4544   "vg_free", FBytes;
4545   "vg_sysid", FString;
4546   "vg_extent_size", FBytes;
4547   "vg_extent_count", FInt64;
4548   "vg_free_count", FInt64;
4549   "max_lv", FInt64;
4550   "max_pv", FInt64;
4551   "pv_count", FInt64;
4552   "lv_count", FInt64;
4553   "snap_count", FInt64;
4554   "vg_seqno", FInt64;
4555   "vg_tags", FString;
4556   "vg_mda_count", FInt64;
4557   "vg_mda_free", FBytes;
4558   (* Not in Fedora 10:
4559      "vg_mda_size", FBytes;
4560   *)
4561 ]
4562 let lvm_lv_cols = [
4563   "lv_name", FString;
4564   "lv_uuid", FUUID;
4565   "lv_attr", FString (* XXX *);
4566   "lv_major", FInt64;
4567   "lv_minor", FInt64;
4568   "lv_kernel_major", FInt64;
4569   "lv_kernel_minor", FInt64;
4570   "lv_size", FBytes;
4571   "seg_count", FInt64;
4572   "origin", FString;
4573   "snap_percent", FOptPercent;
4574   "copy_percent", FOptPercent;
4575   "move_pv", FString;
4576   "lv_tags", FString;
4577   "mirror_log", FString;
4578   "modules", FString;
4579 ]
4580
4581 (* Names and fields in all structures (in RStruct and RStructList)
4582  * that we support.
4583  *)
4584 let structs = [
4585   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4586    * not use this struct in any new code.
4587    *)
4588   "int_bool", [
4589     "i", FInt32;                (* for historical compatibility *)
4590     "b", FInt32;                (* for historical compatibility *)
4591   ];
4592
4593   (* LVM PVs, VGs, LVs. *)
4594   "lvm_pv", lvm_pv_cols;
4595   "lvm_vg", lvm_vg_cols;
4596   "lvm_lv", lvm_lv_cols;
4597
4598   (* Column names and types from stat structures.
4599    * NB. Can't use things like 'st_atime' because glibc header files
4600    * define some of these as macros.  Ugh.
4601    *)
4602   "stat", [
4603     "dev", FInt64;
4604     "ino", FInt64;
4605     "mode", FInt64;
4606     "nlink", FInt64;
4607     "uid", FInt64;
4608     "gid", FInt64;
4609     "rdev", FInt64;
4610     "size", FInt64;
4611     "blksize", FInt64;
4612     "blocks", FInt64;
4613     "atime", FInt64;
4614     "mtime", FInt64;
4615     "ctime", FInt64;
4616   ];
4617   "statvfs", [
4618     "bsize", FInt64;
4619     "frsize", FInt64;
4620     "blocks", FInt64;
4621     "bfree", FInt64;
4622     "bavail", FInt64;
4623     "files", FInt64;
4624     "ffree", FInt64;
4625     "favail", FInt64;
4626     "fsid", FInt64;
4627     "flag", FInt64;
4628     "namemax", FInt64;
4629   ];
4630
4631   (* Column names in dirent structure. *)
4632   "dirent", [
4633     "ino", FInt64;
4634     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4635     "ftyp", FChar;
4636     "name", FString;
4637   ];
4638
4639   (* Version numbers. *)
4640   "version", [
4641     "major", FInt64;
4642     "minor", FInt64;
4643     "release", FInt64;
4644     "extra", FString;
4645   ];
4646
4647   (* Extended attribute. *)
4648   "xattr", [
4649     "attrname", FString;
4650     "attrval", FBuffer;
4651   ];
4652
4653   (* Inotify events. *)
4654   "inotify_event", [
4655     "in_wd", FInt64;
4656     "in_mask", FUInt32;
4657     "in_cookie", FUInt32;
4658     "in_name", FString;
4659   ];
4660
4661   (* Partition table entry. *)
4662   "partition", [
4663     "part_num", FInt32;
4664     "part_start", FBytes;
4665     "part_end", FBytes;
4666     "part_size", FBytes;
4667   ];
4668 ] (* end of structs *)
4669
4670 (* Ugh, Java has to be different ..
4671  * These names are also used by the Haskell bindings.
4672  *)
4673 let java_structs = [
4674   "int_bool", "IntBool";
4675   "lvm_pv", "PV";
4676   "lvm_vg", "VG";
4677   "lvm_lv", "LV";
4678   "stat", "Stat";
4679   "statvfs", "StatVFS";
4680   "dirent", "Dirent";
4681   "version", "Version";
4682   "xattr", "XAttr";
4683   "inotify_event", "INotifyEvent";
4684   "partition", "Partition";
4685 ]
4686
4687 (* What structs are actually returned. *)
4688 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4689
4690 (* Returns a list of RStruct/RStructList structs that are returned
4691  * by any function.  Each element of returned list is a pair:
4692  *
4693  * (structname, RStructOnly)
4694  *    == there exists function which returns RStruct (_, structname)
4695  * (structname, RStructListOnly)
4696  *    == there exists function which returns RStructList (_, structname)
4697  * (structname, RStructAndList)
4698  *    == there are functions returning both RStruct (_, structname)
4699  *                                      and RStructList (_, structname)
4700  *)
4701 let rstructs_used_by functions =
4702   (* ||| is a "logical OR" for rstructs_used_t *)
4703   let (|||) a b =
4704     match a, b with
4705     | RStructAndList, _
4706     | _, RStructAndList -> RStructAndList
4707     | RStructOnly, RStructListOnly
4708     | RStructListOnly, RStructOnly -> RStructAndList
4709     | RStructOnly, RStructOnly -> RStructOnly
4710     | RStructListOnly, RStructListOnly -> RStructListOnly
4711   in
4712
4713   let h = Hashtbl.create 13 in
4714
4715   (* if elem->oldv exists, update entry using ||| operator,
4716    * else just add elem->newv to the hash
4717    *)
4718   let update elem newv =
4719     try  let oldv = Hashtbl.find h elem in
4720          Hashtbl.replace h elem (newv ||| oldv)
4721     with Not_found -> Hashtbl.add h elem newv
4722   in
4723
4724   List.iter (
4725     fun (_, style, _, _, _, _, _) ->
4726       match fst style with
4727       | RStruct (_, structname) -> update structname RStructOnly
4728       | RStructList (_, structname) -> update structname RStructListOnly
4729       | _ -> ()
4730   ) functions;
4731
4732   (* return key->values as a list of (key,value) *)
4733   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4734
4735 (* Used for testing language bindings. *)
4736 type callt =
4737   | CallString of string
4738   | CallOptString of string option
4739   | CallStringList of string list
4740   | CallInt of int
4741   | CallInt64 of int64
4742   | CallBool of bool
4743
4744 (* Used to memoize the result of pod2text. *)
4745 let pod2text_memo_filename = "src/.pod2text.data"
4746 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4747   try
4748     let chan = open_in pod2text_memo_filename in
4749     let v = input_value chan in
4750     close_in chan;
4751     v
4752   with
4753     _ -> Hashtbl.create 13
4754 let pod2text_memo_updated () =
4755   let chan = open_out pod2text_memo_filename in
4756   output_value chan pod2text_memo;
4757   close_out chan
4758
4759 (* Useful functions.
4760  * Note we don't want to use any external OCaml libraries which
4761  * makes this a bit harder than it should be.
4762  *)
4763 module StringMap = Map.Make (String)
4764
4765 let failwithf fs = ksprintf failwith fs
4766
4767 let unique = let i = ref 0 in fun () -> incr i; !i
4768
4769 let replace_char s c1 c2 =
4770   let s2 = String.copy s in
4771   let r = ref false in
4772   for i = 0 to String.length s2 - 1 do
4773     if String.unsafe_get s2 i = c1 then (
4774       String.unsafe_set s2 i c2;
4775       r := true
4776     )
4777   done;
4778   if not !r then s else s2
4779
4780 let isspace c =
4781   c = ' '
4782   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4783
4784 let triml ?(test = isspace) str =
4785   let i = ref 0 in
4786   let n = ref (String.length str) in
4787   while !n > 0 && test str.[!i]; do
4788     decr n;
4789     incr i
4790   done;
4791   if !i = 0 then str
4792   else String.sub str !i !n
4793
4794 let trimr ?(test = isspace) str =
4795   let n = ref (String.length str) in
4796   while !n > 0 && test str.[!n-1]; do
4797     decr n
4798   done;
4799   if !n = String.length str then str
4800   else String.sub str 0 !n
4801
4802 let trim ?(test = isspace) str =
4803   trimr ~test (triml ~test str)
4804
4805 let rec find s sub =
4806   let len = String.length s in
4807   let sublen = String.length sub in
4808   let rec loop i =
4809     if i <= len-sublen then (
4810       let rec loop2 j =
4811         if j < sublen then (
4812           if s.[i+j] = sub.[j] then loop2 (j+1)
4813           else -1
4814         ) else
4815           i (* found *)
4816       in
4817       let r = loop2 0 in
4818       if r = -1 then loop (i+1) else r
4819     ) else
4820       -1 (* not found *)
4821   in
4822   loop 0
4823
4824 let rec replace_str s s1 s2 =
4825   let len = String.length s in
4826   let sublen = String.length s1 in
4827   let i = find s s1 in
4828   if i = -1 then s
4829   else (
4830     let s' = String.sub s 0 i in
4831     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4832     s' ^ s2 ^ replace_str s'' s1 s2
4833   )
4834
4835 let rec string_split sep str =
4836   let len = String.length str in
4837   let seplen = String.length sep in
4838   let i = find str sep in
4839   if i = -1 then [str]
4840   else (
4841     let s' = String.sub str 0 i in
4842     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4843     s' :: string_split sep s''
4844   )
4845
4846 let files_equal n1 n2 =
4847   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4848   match Sys.command cmd with
4849   | 0 -> true
4850   | 1 -> false
4851   | i -> failwithf "%s: failed with error code %d" cmd i
4852
4853 let rec filter_map f = function
4854   | [] -> []
4855   | x :: xs ->
4856       match f x with
4857       | Some y -> y :: filter_map f xs
4858       | None -> filter_map f xs
4859
4860 let rec find_map f = function
4861   | [] -> raise Not_found
4862   | x :: xs ->
4863       match f x with
4864       | Some y -> y
4865       | None -> find_map f xs
4866
4867 let iteri f xs =
4868   let rec loop i = function
4869     | [] -> ()
4870     | x :: xs -> f i x; loop (i+1) xs
4871   in
4872   loop 0 xs
4873
4874 let mapi f xs =
4875   let rec loop i = function
4876     | [] -> []
4877     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4878   in
4879   loop 0 xs
4880
4881 let count_chars c str =
4882   let count = ref 0 in
4883   for i = 0 to String.length str - 1 do
4884     if c = String.unsafe_get str i then incr count
4885   done;
4886   !count
4887
4888 let name_of_argt = function
4889   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4890   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4891   | FileIn n | FileOut n -> n
4892
4893 let java_name_of_struct typ =
4894   try List.assoc typ java_structs
4895   with Not_found ->
4896     failwithf
4897       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4898
4899 let cols_of_struct typ =
4900   try List.assoc typ structs
4901   with Not_found ->
4902     failwithf "cols_of_struct: unknown struct %s" typ
4903
4904 let seq_of_test = function
4905   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4906   | TestOutputListOfDevices (s, _)
4907   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4908   | TestOutputTrue s | TestOutputFalse s
4909   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4910   | TestOutputStruct (s, _)
4911   | TestLastFail s -> s
4912
4913 (* Handling for function flags. *)
4914 let protocol_limit_warning =
4915   "Because of the message protocol, there is a transfer limit
4916 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4917
4918 let danger_will_robinson =
4919   "B<This command is dangerous.  Without careful use you
4920 can easily destroy all your data>."
4921
4922 let deprecation_notice flags =
4923   try
4924     let alt =
4925       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4926     let txt =
4927       sprintf "This function is deprecated.
4928 In new code, use the C<%s> call instead.
4929
4930 Deprecated functions will not be removed from the API, but the
4931 fact that they are deprecated indicates that there are problems
4932 with correct use of these functions." alt in
4933     Some txt
4934   with
4935     Not_found -> None
4936
4937 (* Create list of optional groups. *)
4938 let optgroups =
4939   let h = Hashtbl.create 13 in
4940   List.iter (
4941     fun (name, _, _, flags, _, _, _) ->
4942       List.iter (
4943         function
4944         | Optional group ->
4945             let names = try Hashtbl.find h group with Not_found -> [] in
4946             Hashtbl.replace h group (name :: names)
4947         | _ -> ()
4948       ) flags
4949   ) daemon_functions;
4950   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4951   let groups =
4952     List.map (
4953       fun group -> group, List.sort compare (Hashtbl.find h group)
4954     ) groups in
4955   List.sort (fun x y -> compare (fst x) (fst y)) groups
4956
4957 (* Check function names etc. for consistency. *)
4958 let check_functions () =
4959   let contains_uppercase str =
4960     let len = String.length str in
4961     let rec loop i =
4962       if i >= len then false
4963       else (
4964         let c = str.[i] in
4965         if c >= 'A' && c <= 'Z' then true
4966         else loop (i+1)
4967       )
4968     in
4969     loop 0
4970   in
4971
4972   (* Check function names. *)
4973   List.iter (
4974     fun (name, _, _, _, _, _, _) ->
4975       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4976         failwithf "function name %s does not need 'guestfs' prefix" name;
4977       if name = "" then
4978         failwithf "function name is empty";
4979       if name.[0] < 'a' || name.[0] > 'z' then
4980         failwithf "function name %s must start with lowercase a-z" name;
4981       if String.contains name '-' then
4982         failwithf "function name %s should not contain '-', use '_' instead."
4983           name
4984   ) all_functions;
4985
4986   (* Check function parameter/return names. *)
4987   List.iter (
4988     fun (name, style, _, _, _, _, _) ->
4989       let check_arg_ret_name n =
4990         if contains_uppercase n then
4991           failwithf "%s param/ret %s should not contain uppercase chars"
4992             name n;
4993         if String.contains n '-' || String.contains n '_' then
4994           failwithf "%s param/ret %s should not contain '-' or '_'"
4995             name n;
4996         if n = "value" then
4997           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;
4998         if n = "int" || n = "char" || n = "short" || n = "long" then
4999           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5000         if n = "i" || n = "n" then
5001           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5002         if n = "argv" || n = "args" then
5003           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5004
5005         (* List Haskell, OCaml and C keywords here.
5006          * http://www.haskell.org/haskellwiki/Keywords
5007          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5008          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5009          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5010          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5011          * Omitting _-containing words, since they're handled above.
5012          * Omitting the OCaml reserved word, "val", is ok,
5013          * and saves us from renaming several parameters.
5014          *)
5015         let reserved = [
5016           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5017           "char"; "class"; "const"; "constraint"; "continue"; "data";
5018           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5019           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5020           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5021           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5022           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5023           "interface";
5024           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5025           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5026           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5027           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5028           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5029           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5030           "volatile"; "when"; "where"; "while";
5031           ] in
5032         if List.mem n reserved then
5033           failwithf "%s has param/ret using reserved word %s" name n;
5034       in
5035
5036       (match fst style with
5037        | RErr -> ()
5038        | RInt n | RInt64 n | RBool n
5039        | RConstString n | RConstOptString n | RString n
5040        | RStringList n | RStruct (n, _) | RStructList (n, _)
5041        | RHashtable n | RBufferOut n ->
5042            check_arg_ret_name n
5043       );
5044       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5045   ) all_functions;
5046
5047   (* Check short descriptions. *)
5048   List.iter (
5049     fun (name, _, _, _, _, shortdesc, _) ->
5050       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5051         failwithf "short description of %s should begin with lowercase." name;
5052       let c = shortdesc.[String.length shortdesc-1] in
5053       if c = '\n' || c = '.' then
5054         failwithf "short description of %s should not end with . or \\n." name
5055   ) all_functions;
5056
5057   (* Check long descriptions. *)
5058   List.iter (
5059     fun (name, _, _, _, _, _, longdesc) ->
5060       if longdesc.[String.length longdesc-1] = '\n' then
5061         failwithf "long description of %s should not end with \\n." name
5062   ) all_functions;
5063
5064   (* Check proc_nrs. *)
5065   List.iter (
5066     fun (name, _, proc_nr, _, _, _, _) ->
5067       if proc_nr <= 0 then
5068         failwithf "daemon function %s should have proc_nr > 0" name
5069   ) daemon_functions;
5070
5071   List.iter (
5072     fun (name, _, proc_nr, _, _, _, _) ->
5073       if proc_nr <> -1 then
5074         failwithf "non-daemon function %s should have proc_nr -1" name
5075   ) non_daemon_functions;
5076
5077   let proc_nrs =
5078     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5079       daemon_functions in
5080   let proc_nrs =
5081     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5082   let rec loop = function
5083     | [] -> ()
5084     | [_] -> ()
5085     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5086         loop rest
5087     | (name1,nr1) :: (name2,nr2) :: _ ->
5088         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5089           name1 name2 nr1 nr2
5090   in
5091   loop proc_nrs;
5092
5093   (* Check tests. *)
5094   List.iter (
5095     function
5096       (* Ignore functions that have no tests.  We generate a
5097        * warning when the user does 'make check' instead.
5098        *)
5099     | name, _, _, _, [], _, _ -> ()
5100     | name, _, _, _, tests, _, _ ->
5101         let funcs =
5102           List.map (
5103             fun (_, _, test) ->
5104               match seq_of_test test with
5105               | [] ->
5106                   failwithf "%s has a test containing an empty sequence" name
5107               | cmds -> List.map List.hd cmds
5108           ) tests in
5109         let funcs = List.flatten funcs in
5110
5111         let tested = List.mem name funcs in
5112
5113         if not tested then
5114           failwithf "function %s has tests but does not test itself" name
5115   ) all_functions
5116
5117 (* 'pr' prints to the current output file. *)
5118 let chan = ref Pervasives.stdout
5119 let lines = ref 0
5120 let pr fs =
5121   ksprintf
5122     (fun str ->
5123        let i = count_chars '\n' str in
5124        lines := !lines + i;
5125        output_string !chan str
5126     ) fs
5127
5128 let copyright_years =
5129   let this_year = 1900 + (localtime (time ())).tm_year in
5130   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5131
5132 (* Generate a header block in a number of standard styles. *)
5133 type comment_style =
5134     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5135 type license = GPLv2plus | LGPLv2plus
5136
5137 let generate_header ?(extra_inputs = []) comment license =
5138   let inputs = "src/generator.ml" :: extra_inputs in
5139   let c = match comment with
5140     | CStyle ->         pr "/* "; " *"
5141     | CPlusPlusStyle -> pr "// "; "//"
5142     | HashStyle ->      pr "# ";  "#"
5143     | OCamlStyle ->     pr "(* "; " *"
5144     | HaskellStyle ->   pr "{- "; "  " in
5145   pr "libguestfs generated file\n";
5146   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5147   List.iter (pr "%s   %s\n" c) inputs;
5148   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5149   pr "%s\n" c;
5150   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5151   pr "%s\n" c;
5152   (match license with
5153    | GPLv2plus ->
5154        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5155        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5156        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5157        pr "%s (at your option) any later version.\n" c;
5158        pr "%s\n" c;
5159        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5160        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5161        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5162        pr "%s GNU General Public License for more details.\n" c;
5163        pr "%s\n" c;
5164        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5165        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5166        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5167
5168    | LGPLv2plus ->
5169        pr "%s This library is free software; you can redistribute it and/or\n" c;
5170        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5171        pr "%s License as published by the Free Software Foundation; either\n" c;
5172        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5173        pr "%s\n" c;
5174        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5175        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5176        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5177        pr "%s Lesser General Public License for more details.\n" c;
5178        pr "%s\n" c;
5179        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5180        pr "%s License along with this library; if not, write to the Free Software\n" c;
5181        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5182   );
5183   (match comment with
5184    | CStyle -> pr " */\n"
5185    | CPlusPlusStyle
5186    | HashStyle -> ()
5187    | OCamlStyle -> pr " *)\n"
5188    | HaskellStyle -> pr "-}\n"
5189   );
5190   pr "\n"
5191
5192 (* Start of main code generation functions below this line. *)
5193
5194 (* Generate the pod documentation for the C API. *)
5195 let rec generate_actions_pod () =
5196   List.iter (
5197     fun (shortname, style, _, flags, _, _, longdesc) ->
5198       if not (List.mem NotInDocs flags) then (
5199         let name = "guestfs_" ^ shortname in
5200         pr "=head2 %s\n\n" name;
5201         pr " ";
5202         generate_prototype ~extern:false ~handle:"g" name style;
5203         pr "\n\n";
5204         pr "%s\n\n" longdesc;
5205         (match fst style with
5206          | RErr ->
5207              pr "This function returns 0 on success or -1 on error.\n\n"
5208          | RInt _ ->
5209              pr "On error this function returns -1.\n\n"
5210          | RInt64 _ ->
5211              pr "On error this function returns -1.\n\n"
5212          | RBool _ ->
5213              pr "This function returns a C truth value on success or -1 on error.\n\n"
5214          | RConstString _ ->
5215              pr "This function returns a string, or NULL on error.
5216 The string is owned by the guest handle and must I<not> be freed.\n\n"
5217          | RConstOptString _ ->
5218              pr "This function returns a string which may be NULL.
5219 There is way to return an error from this function.
5220 The string is owned by the guest handle and must I<not> be freed.\n\n"
5221          | RString _ ->
5222              pr "This function returns a string, or NULL on error.
5223 I<The caller must free the returned string after use>.\n\n"
5224          | RStringList _ ->
5225              pr "This function returns a NULL-terminated array of strings
5226 (like L<environ(3)>), or NULL if there was an error.
5227 I<The caller must free the strings and the array after use>.\n\n"
5228          | RStruct (_, typ) ->
5229              pr "This function returns a C<struct guestfs_%s *>,
5230 or NULL if there was an error.
5231 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5232          | RStructList (_, typ) ->
5233              pr "This function returns a C<struct guestfs_%s_list *>
5234 (see E<lt>guestfs-structs.hE<gt>),
5235 or NULL if there was an error.
5236 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5237          | RHashtable _ ->
5238              pr "This function returns a NULL-terminated array of
5239 strings, or NULL if there was an error.
5240 The array of strings will always have length C<2n+1>, where
5241 C<n> keys and values alternate, followed by the trailing NULL entry.
5242 I<The caller must free the strings and the array after use>.\n\n"
5243          | RBufferOut _ ->
5244              pr "This function returns a buffer, or NULL on error.
5245 The size of the returned buffer is written to C<*size_r>.
5246 I<The caller must free the returned buffer after use>.\n\n"
5247         );
5248         if List.mem ProtocolLimitWarning flags then
5249           pr "%s\n\n" protocol_limit_warning;
5250         if List.mem DangerWillRobinson flags then
5251           pr "%s\n\n" danger_will_robinson;
5252         match deprecation_notice flags with
5253         | None -> ()
5254         | Some txt -> pr "%s\n\n" txt
5255       )
5256   ) all_functions_sorted
5257
5258 and generate_structs_pod () =
5259   (* Structs documentation. *)
5260   List.iter (
5261     fun (typ, cols) ->
5262       pr "=head2 guestfs_%s\n" typ;
5263       pr "\n";
5264       pr " struct guestfs_%s {\n" typ;
5265       List.iter (
5266         function
5267         | name, FChar -> pr "   char %s;\n" name
5268         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5269         | name, FInt32 -> pr "   int32_t %s;\n" name
5270         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5271         | name, FInt64 -> pr "   int64_t %s;\n" name
5272         | name, FString -> pr "   char *%s;\n" name
5273         | name, FBuffer ->
5274             pr "   /* The next two fields describe a byte array. */\n";
5275             pr "   uint32_t %s_len;\n" name;
5276             pr "   char *%s;\n" name
5277         | name, FUUID ->
5278             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5279             pr "   char %s[32];\n" name
5280         | name, FOptPercent ->
5281             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5282             pr "   float %s;\n" name
5283       ) cols;
5284       pr " };\n";
5285       pr " \n";
5286       pr " struct guestfs_%s_list {\n" typ;
5287       pr "   uint32_t len; /* Number of elements in list. */\n";
5288       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5289       pr " };\n";
5290       pr " \n";
5291       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5292       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5293         typ typ;
5294       pr "\n"
5295   ) structs
5296
5297 and generate_availability_pod () =
5298   (* Availability documentation. *)
5299   pr "=over 4\n";
5300   pr "\n";
5301   List.iter (
5302     fun (group, functions) ->
5303       pr "=item B<%s>\n" group;
5304       pr "\n";
5305       pr "The following functions:\n";
5306       List.iter (pr "L</guestfs_%s>\n") functions;
5307       pr "\n"
5308   ) optgroups;
5309   pr "=back\n";
5310   pr "\n"
5311
5312 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5313  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5314  *
5315  * We have to use an underscore instead of a dash because otherwise
5316  * rpcgen generates incorrect code.
5317  *
5318  * This header is NOT exported to clients, but see also generate_structs_h.
5319  *)
5320 and generate_xdr () =
5321   generate_header CStyle LGPLv2plus;
5322
5323   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5324   pr "typedef string str<>;\n";
5325   pr "\n";
5326
5327   (* Internal structures. *)
5328   List.iter (
5329     function
5330     | typ, cols ->
5331         pr "struct guestfs_int_%s {\n" typ;
5332         List.iter (function
5333                    | name, FChar -> pr "  char %s;\n" name
5334                    | name, FString -> pr "  string %s<>;\n" name
5335                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5336                    | name, FUUID -> pr "  opaque %s[32];\n" name
5337                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5338                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5339                    | name, FOptPercent -> pr "  float %s;\n" name
5340                   ) cols;
5341         pr "};\n";
5342         pr "\n";
5343         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5344         pr "\n";
5345   ) structs;
5346
5347   List.iter (
5348     fun (shortname, style, _, _, _, _, _) ->
5349       let name = "guestfs_" ^ shortname in
5350
5351       (match snd style with
5352        | [] -> ()
5353        | args ->
5354            pr "struct %s_args {\n" name;
5355            List.iter (
5356              function
5357              | Pathname n | Device n | Dev_or_Path n | String n ->
5358                  pr "  string %s<>;\n" n
5359              | OptString n -> pr "  str *%s;\n" n
5360              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5361              | Bool n -> pr "  bool %s;\n" n
5362              | Int n -> pr "  int %s;\n" n
5363              | Int64 n -> pr "  hyper %s;\n" n
5364              | FileIn _ | FileOut _ -> ()
5365            ) args;
5366            pr "};\n\n"
5367       );
5368       (match fst style with
5369        | RErr -> ()
5370        | RInt n ->
5371            pr "struct %s_ret {\n" name;
5372            pr "  int %s;\n" n;
5373            pr "};\n\n"
5374        | RInt64 n ->
5375            pr "struct %s_ret {\n" name;
5376            pr "  hyper %s;\n" n;
5377            pr "};\n\n"
5378        | RBool n ->
5379            pr "struct %s_ret {\n" name;
5380            pr "  bool %s;\n" n;
5381            pr "};\n\n"
5382        | RConstString _ | RConstOptString _ ->
5383            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5384        | RString n ->
5385            pr "struct %s_ret {\n" name;
5386            pr "  string %s<>;\n" n;
5387            pr "};\n\n"
5388        | RStringList n ->
5389            pr "struct %s_ret {\n" name;
5390            pr "  str %s<>;\n" n;
5391            pr "};\n\n"
5392        | RStruct (n, typ) ->
5393            pr "struct %s_ret {\n" name;
5394            pr "  guestfs_int_%s %s;\n" typ n;
5395            pr "};\n\n"
5396        | RStructList (n, typ) ->
5397            pr "struct %s_ret {\n" name;
5398            pr "  guestfs_int_%s_list %s;\n" typ n;
5399            pr "};\n\n"
5400        | RHashtable n ->
5401            pr "struct %s_ret {\n" name;
5402            pr "  str %s<>;\n" n;
5403            pr "};\n\n"
5404        | RBufferOut n ->
5405            pr "struct %s_ret {\n" name;
5406            pr "  opaque %s<>;\n" n;
5407            pr "};\n\n"
5408       );
5409   ) daemon_functions;
5410
5411   (* Table of procedure numbers. *)
5412   pr "enum guestfs_procedure {\n";
5413   List.iter (
5414     fun (shortname, _, proc_nr, _, _, _, _) ->
5415       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5416   ) daemon_functions;
5417   pr "  GUESTFS_PROC_NR_PROCS\n";
5418   pr "};\n";
5419   pr "\n";
5420
5421   (* Having to choose a maximum message size is annoying for several
5422    * reasons (it limits what we can do in the API), but it (a) makes
5423    * the protocol a lot simpler, and (b) provides a bound on the size
5424    * of the daemon which operates in limited memory space.
5425    *)
5426   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5427   pr "\n";
5428
5429   (* Message header, etc. *)
5430   pr "\
5431 /* The communication protocol is now documented in the guestfs(3)
5432  * manpage.
5433  */
5434
5435 const GUESTFS_PROGRAM = 0x2000F5F5;
5436 const GUESTFS_PROTOCOL_VERSION = 1;
5437
5438 /* These constants must be larger than any possible message length. */
5439 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5440 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5441
5442 enum guestfs_message_direction {
5443   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5444   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5445 };
5446
5447 enum guestfs_message_status {
5448   GUESTFS_STATUS_OK = 0,
5449   GUESTFS_STATUS_ERROR = 1
5450 };
5451
5452 const GUESTFS_ERROR_LEN = 256;
5453
5454 struct guestfs_message_error {
5455   string error_message<GUESTFS_ERROR_LEN>;
5456 };
5457
5458 struct guestfs_message_header {
5459   unsigned prog;                     /* GUESTFS_PROGRAM */
5460   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5461   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5462   guestfs_message_direction direction;
5463   unsigned serial;                   /* message serial number */
5464   guestfs_message_status status;
5465 };
5466
5467 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5468
5469 struct guestfs_chunk {
5470   int cancel;                        /* if non-zero, transfer is cancelled */
5471   /* data size is 0 bytes if the transfer has finished successfully */
5472   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5473 };
5474 "
5475
5476 (* Generate the guestfs-structs.h file. *)
5477 and generate_structs_h () =
5478   generate_header CStyle LGPLv2plus;
5479
5480   (* This is a public exported header file containing various
5481    * structures.  The structures are carefully written to have
5482    * exactly the same in-memory format as the XDR structures that
5483    * we use on the wire to the daemon.  The reason for creating
5484    * copies of these structures here is just so we don't have to
5485    * export the whole of guestfs_protocol.h (which includes much
5486    * unrelated and XDR-dependent stuff that we don't want to be
5487    * public, or required by clients).
5488    *
5489    * To reiterate, we will pass these structures to and from the
5490    * client with a simple assignment or memcpy, so the format
5491    * must be identical to what rpcgen / the RFC defines.
5492    *)
5493
5494   (* Public structures. *)
5495   List.iter (
5496     fun (typ, cols) ->
5497       pr "struct guestfs_%s {\n" typ;
5498       List.iter (
5499         function
5500         | name, FChar -> pr "  char %s;\n" name
5501         | name, FString -> pr "  char *%s;\n" name
5502         | name, FBuffer ->
5503             pr "  uint32_t %s_len;\n" name;
5504             pr "  char *%s;\n" name
5505         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5506         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5507         | name, FInt32 -> pr "  int32_t %s;\n" name
5508         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5509         | name, FInt64 -> pr "  int64_t %s;\n" name
5510         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5511       ) cols;
5512       pr "};\n";
5513       pr "\n";
5514       pr "struct guestfs_%s_list {\n" typ;
5515       pr "  uint32_t len;\n";
5516       pr "  struct guestfs_%s *val;\n" typ;
5517       pr "};\n";
5518       pr "\n";
5519       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5520       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5521       pr "\n"
5522   ) structs
5523
5524 (* Generate the guestfs-actions.h file. *)
5525 and generate_actions_h () =
5526   generate_header CStyle LGPLv2plus;
5527   List.iter (
5528     fun (shortname, style, _, _, _, _, _) ->
5529       let name = "guestfs_" ^ shortname in
5530       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5531         name style
5532   ) all_functions
5533
5534 (* Generate the guestfs-internal-actions.h file. *)
5535 and generate_internal_actions_h () =
5536   generate_header CStyle LGPLv2plus;
5537   List.iter (
5538     fun (shortname, style, _, _, _, _, _) ->
5539       let name = "guestfs__" ^ shortname in
5540       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5541         name style
5542   ) non_daemon_functions
5543
5544 (* Generate the client-side dispatch stubs. *)
5545 and generate_client_actions () =
5546   generate_header CStyle LGPLv2plus;
5547
5548   pr "\
5549 #include <stdio.h>
5550 #include <stdlib.h>
5551 #include <stdint.h>
5552 #include <string.h>
5553 #include <inttypes.h>
5554
5555 #include \"guestfs.h\"
5556 #include \"guestfs-internal.h\"
5557 #include \"guestfs-internal-actions.h\"
5558 #include \"guestfs_protocol.h\"
5559
5560 #define error guestfs_error
5561 //#define perrorf guestfs_perrorf
5562 #define safe_malloc guestfs_safe_malloc
5563 #define safe_realloc guestfs_safe_realloc
5564 //#define safe_strdup guestfs_safe_strdup
5565 #define safe_memdup guestfs_safe_memdup
5566
5567 /* Check the return message from a call for validity. */
5568 static int
5569 check_reply_header (guestfs_h *g,
5570                     const struct guestfs_message_header *hdr,
5571                     unsigned int proc_nr, unsigned int serial)
5572 {
5573   if (hdr->prog != GUESTFS_PROGRAM) {
5574     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5575     return -1;
5576   }
5577   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5578     error (g, \"wrong protocol version (%%d/%%d)\",
5579            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5580     return -1;
5581   }
5582   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5583     error (g, \"unexpected message direction (%%d/%%d)\",
5584            hdr->direction, GUESTFS_DIRECTION_REPLY);
5585     return -1;
5586   }
5587   if (hdr->proc != proc_nr) {
5588     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5589     return -1;
5590   }
5591   if (hdr->serial != serial) {
5592     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5593     return -1;
5594   }
5595
5596   return 0;
5597 }
5598
5599 /* Check we are in the right state to run a high-level action. */
5600 static int
5601 check_state (guestfs_h *g, const char *caller)
5602 {
5603   if (!guestfs__is_ready (g)) {
5604     if (guestfs__is_config (g) || guestfs__is_launching (g))
5605       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5606         caller);
5607     else
5608       error (g, \"%%s called from the wrong state, %%d != READY\",
5609         caller, guestfs__get_state (g));
5610     return -1;
5611   }
5612   return 0;
5613 }
5614
5615 ";
5616
5617   (* Generate code to generate guestfish call traces. *)
5618   let trace_call shortname style =
5619     pr "  if (guestfs__get_trace (g)) {\n";
5620
5621     let needs_i =
5622       List.exists (function
5623                    | StringList _ | DeviceList _ -> true
5624                    | _ -> false) (snd style) in
5625     if needs_i then (
5626       pr "    int i;\n";
5627       pr "\n"
5628     );
5629
5630     pr "    printf (\"%s\");\n" shortname;
5631     List.iter (
5632       function
5633       | String n                        (* strings *)
5634       | Device n
5635       | Pathname n
5636       | Dev_or_Path n
5637       | FileIn n
5638       | FileOut n ->
5639           (* guestfish doesn't support string escaping, so neither do we *)
5640           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5641       | OptString n ->                  (* string option *)
5642           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5643           pr "    else printf (\" null\");\n"
5644       | StringList n
5645       | DeviceList n ->                 (* string list *)
5646           pr "    putchar (' ');\n";
5647           pr "    putchar ('\"');\n";
5648           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5649           pr "      if (i > 0) putchar (' ');\n";
5650           pr "      fputs (%s[i], stdout);\n" n;
5651           pr "    }\n";
5652           pr "    putchar ('\"');\n";
5653       | Bool n ->                       (* boolean *)
5654           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5655       | Int n ->                        (* int *)
5656           pr "    printf (\" %%d\", %s);\n" n
5657       | Int64 n ->
5658           pr "    printf (\" %%\" PRIi64, %s);\n" n
5659     ) (snd style);
5660     pr "    putchar ('\\n');\n";
5661     pr "  }\n";
5662     pr "\n";
5663   in
5664
5665   (* For non-daemon functions, generate a wrapper around each function. *)
5666   List.iter (
5667     fun (shortname, style, _, _, _, _, _) ->
5668       let name = "guestfs_" ^ shortname in
5669
5670       generate_prototype ~extern:false ~semicolon:false ~newline:true
5671         ~handle:"g" name style;
5672       pr "{\n";
5673       trace_call shortname style;
5674       pr "  return guestfs__%s " shortname;
5675       generate_c_call_args ~handle:"g" style;
5676       pr ";\n";
5677       pr "}\n";
5678       pr "\n"
5679   ) non_daemon_functions;
5680
5681   (* Client-side stubs for each function. *)
5682   List.iter (
5683     fun (shortname, style, _, _, _, _, _) ->
5684       let name = "guestfs_" ^ shortname in
5685
5686       (* Generate the action stub. *)
5687       generate_prototype ~extern:false ~semicolon:false ~newline:true
5688         ~handle:"g" name style;
5689
5690       let error_code =
5691         match fst style with
5692         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5693         | RConstString _ | RConstOptString _ ->
5694             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5695         | RString _ | RStringList _
5696         | RStruct _ | RStructList _
5697         | RHashtable _ | RBufferOut _ ->
5698             "NULL" in
5699
5700       pr "{\n";
5701
5702       (match snd style with
5703        | [] -> ()
5704        | _ -> pr "  struct %s_args args;\n" name
5705       );
5706
5707       pr "  guestfs_message_header hdr;\n";
5708       pr "  guestfs_message_error err;\n";
5709       let has_ret =
5710         match fst style with
5711         | RErr -> false
5712         | RConstString _ | RConstOptString _ ->
5713             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5714         | RInt _ | RInt64 _
5715         | RBool _ | RString _ | RStringList _
5716         | RStruct _ | RStructList _
5717         | RHashtable _ | RBufferOut _ ->
5718             pr "  struct %s_ret ret;\n" name;
5719             true in
5720
5721       pr "  int serial;\n";
5722       pr "  int r;\n";
5723       pr "\n";
5724       trace_call shortname style;
5725       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5726       pr "  guestfs___set_busy (g);\n";
5727       pr "\n";
5728
5729       (* Send the main header and arguments. *)
5730       (match snd style with
5731        | [] ->
5732            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5733              (String.uppercase shortname)
5734        | args ->
5735            List.iter (
5736              function
5737              | Pathname n | Device n | Dev_or_Path n | String n ->
5738                  pr "  args.%s = (char *) %s;\n" n n
5739              | OptString n ->
5740                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5741              | StringList n | DeviceList n ->
5742                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5743                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5744              | Bool n ->
5745                  pr "  args.%s = %s;\n" n n
5746              | Int n ->
5747                  pr "  args.%s = %s;\n" n n
5748              | Int64 n ->
5749                  pr "  args.%s = %s;\n" n n
5750              | FileIn _ | FileOut _ -> ()
5751            ) args;
5752            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5753              (String.uppercase shortname);
5754            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5755              name;
5756       );
5757       pr "  if (serial == -1) {\n";
5758       pr "    guestfs___end_busy (g);\n";
5759       pr "    return %s;\n" error_code;
5760       pr "  }\n";
5761       pr "\n";
5762
5763       (* Send any additional files (FileIn) requested. *)
5764       let need_read_reply_label = ref false in
5765       List.iter (
5766         function
5767         | FileIn n ->
5768             pr "  r = guestfs___send_file (g, %s);\n" n;
5769             pr "  if (r == -1) {\n";
5770             pr "    guestfs___end_busy (g);\n";
5771             pr "    return %s;\n" error_code;
5772             pr "  }\n";
5773             pr "  if (r == -2) /* daemon cancelled */\n";
5774             pr "    goto read_reply;\n";
5775             need_read_reply_label := true;
5776             pr "\n";
5777         | _ -> ()
5778       ) (snd style);
5779
5780       (* Wait for the reply from the remote end. *)
5781       if !need_read_reply_label then pr " read_reply:\n";
5782       pr "  memset (&hdr, 0, sizeof hdr);\n";
5783       pr "  memset (&err, 0, sizeof err);\n";
5784       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5785       pr "\n";
5786       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5787       if not has_ret then
5788         pr "NULL, NULL"
5789       else
5790         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5791       pr ");\n";
5792
5793       pr "  if (r == -1) {\n";
5794       pr "    guestfs___end_busy (g);\n";
5795       pr "    return %s;\n" error_code;
5796       pr "  }\n";
5797       pr "\n";
5798
5799       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5800         (String.uppercase shortname);
5801       pr "    guestfs___end_busy (g);\n";
5802       pr "    return %s;\n" error_code;
5803       pr "  }\n";
5804       pr "\n";
5805
5806       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5807       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5808       pr "    free (err.error_message);\n";
5809       pr "    guestfs___end_busy (g);\n";
5810       pr "    return %s;\n" error_code;
5811       pr "  }\n";
5812       pr "\n";
5813
5814       (* Expecting to receive further files (FileOut)? *)
5815       List.iter (
5816         function
5817         | FileOut n ->
5818             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5819             pr "    guestfs___end_busy (g);\n";
5820             pr "    return %s;\n" error_code;
5821             pr "  }\n";
5822             pr "\n";
5823         | _ -> ()
5824       ) (snd style);
5825
5826       pr "  guestfs___end_busy (g);\n";
5827
5828       (match fst style with
5829        | RErr -> pr "  return 0;\n"
5830        | RInt n | RInt64 n | RBool n ->
5831            pr "  return ret.%s;\n" n
5832        | RConstString _ | RConstOptString _ ->
5833            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5834        | RString n ->
5835            pr "  return ret.%s; /* caller will free */\n" n
5836        | RStringList n | RHashtable n ->
5837            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5838            pr "  ret.%s.%s_val =\n" n n;
5839            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5840            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5841              n n;
5842            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5843            pr "  return ret.%s.%s_val;\n" n n
5844        | RStruct (n, _) ->
5845            pr "  /* caller will free this */\n";
5846            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5847        | RStructList (n, _) ->
5848            pr "  /* caller will free this */\n";
5849            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5850        | RBufferOut n ->
5851            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5852            pr "   * _val might be NULL here.  To make the API saner for\n";
5853            pr "   * callers, we turn this case into a unique pointer (using\n";
5854            pr "   * malloc(1)).\n";
5855            pr "   */\n";
5856            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5857            pr "    *size_r = ret.%s.%s_len;\n" n n;
5858            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5859            pr "  } else {\n";
5860            pr "    free (ret.%s.%s_val);\n" n n;
5861            pr "    char *p = safe_malloc (g, 1);\n";
5862            pr "    *size_r = ret.%s.%s_len;\n" n n;
5863            pr "    return p;\n";
5864            pr "  }\n";
5865       );
5866
5867       pr "}\n\n"
5868   ) daemon_functions;
5869
5870   (* Functions to free structures. *)
5871   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5872   pr " * structure format is identical to the XDR format.  See note in\n";
5873   pr " * generator.ml.\n";
5874   pr " */\n";
5875   pr "\n";
5876
5877   List.iter (
5878     fun (typ, _) ->
5879       pr "void\n";
5880       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5881       pr "{\n";
5882       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5883       pr "  free (x);\n";
5884       pr "}\n";
5885       pr "\n";
5886
5887       pr "void\n";
5888       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5889       pr "{\n";
5890       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5891       pr "  free (x);\n";
5892       pr "}\n";
5893       pr "\n";
5894
5895   ) structs;
5896
5897 (* Generate daemon/actions.h. *)
5898 and generate_daemon_actions_h () =
5899   generate_header CStyle GPLv2plus;
5900
5901   pr "#include \"../src/guestfs_protocol.h\"\n";
5902   pr "\n";
5903
5904   List.iter (
5905     fun (name, style, _, _, _, _, _) ->
5906       generate_prototype
5907         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5908         name style;
5909   ) daemon_functions
5910
5911 (* Generate the linker script which controls the visibility of
5912  * symbols in the public ABI and ensures no other symbols get
5913  * exported accidentally.
5914  *)
5915 and generate_linker_script () =
5916   generate_header HashStyle GPLv2plus;
5917
5918   let globals = [
5919     "guestfs_create";
5920     "guestfs_close";
5921     "guestfs_get_error_handler";
5922     "guestfs_get_out_of_memory_handler";
5923     "guestfs_last_error";
5924     "guestfs_set_error_handler";
5925     "guestfs_set_launch_done_callback";
5926     "guestfs_set_log_message_callback";
5927     "guestfs_set_out_of_memory_handler";
5928     "guestfs_set_subprocess_quit_callback";
5929
5930     (* Unofficial parts of the API: the bindings code use these
5931      * functions, so it is useful to export them.
5932      *)
5933     "guestfs_safe_calloc";
5934     "guestfs_safe_malloc";
5935   ] in
5936   let functions =
5937     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5938       all_functions in
5939   let structs =
5940     List.concat (
5941       List.map (fun (typ, _) ->
5942                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5943         structs
5944     ) in
5945   let globals = List.sort compare (globals @ functions @ structs) in
5946
5947   pr "{\n";
5948   pr "    global:\n";
5949   List.iter (pr "        %s;\n") globals;
5950   pr "\n";
5951
5952   pr "    local:\n";
5953   pr "        *;\n";
5954   pr "};\n"
5955
5956 (* Generate the server-side stubs. *)
5957 and generate_daemon_actions () =
5958   generate_header CStyle GPLv2plus;
5959
5960   pr "#include <config.h>\n";
5961   pr "\n";
5962   pr "#include <stdio.h>\n";
5963   pr "#include <stdlib.h>\n";
5964   pr "#include <string.h>\n";
5965   pr "#include <inttypes.h>\n";
5966   pr "#include <rpc/types.h>\n";
5967   pr "#include <rpc/xdr.h>\n";
5968   pr "\n";
5969   pr "#include \"daemon.h\"\n";
5970   pr "#include \"c-ctype.h\"\n";
5971   pr "#include \"../src/guestfs_protocol.h\"\n";
5972   pr "#include \"actions.h\"\n";
5973   pr "\n";
5974
5975   List.iter (
5976     fun (name, style, _, _, _, _, _) ->
5977       (* Generate server-side stubs. *)
5978       pr "static void %s_stub (XDR *xdr_in)\n" name;
5979       pr "{\n";
5980       let error_code =
5981         match fst style with
5982         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5983         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5984         | RBool _ -> pr "  int r;\n"; "-1"
5985         | RConstString _ | RConstOptString _ ->
5986             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5987         | RString _ -> pr "  char *r;\n"; "NULL"
5988         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5989         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5990         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5991         | RBufferOut _ ->
5992             pr "  size_t size = 1;\n";
5993             pr "  char *r;\n";
5994             "NULL" in
5995
5996       (match snd style with
5997        | [] -> ()
5998        | args ->
5999            pr "  struct guestfs_%s_args args;\n" name;
6000            List.iter (
6001              function
6002              | Device n | Dev_or_Path n
6003              | Pathname n
6004              | String n -> ()
6005              | OptString n -> pr "  char *%s;\n" n
6006              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6007              | Bool n -> pr "  int %s;\n" n
6008              | Int n -> pr "  int %s;\n" n
6009              | Int64 n -> pr "  int64_t %s;\n" n
6010              | FileIn _ | FileOut _ -> ()
6011            ) args
6012       );
6013       pr "\n";
6014
6015       (match snd style with
6016        | [] -> ()
6017        | args ->
6018            pr "  memset (&args, 0, sizeof args);\n";
6019            pr "\n";
6020            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6021            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6022            pr "    return;\n";
6023            pr "  }\n";
6024            let pr_args n =
6025              pr "  char *%s = args.%s;\n" n n
6026            in
6027            let pr_list_handling_code n =
6028              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6029              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6030              pr "  if (%s == NULL) {\n" n;
6031              pr "    reply_with_perror (\"realloc\");\n";
6032              pr "    goto done;\n";
6033              pr "  }\n";
6034              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6035              pr "  args.%s.%s_val = %s;\n" n n n;
6036            in
6037            List.iter (
6038              function
6039              | Pathname n ->
6040                  pr_args n;
6041                  pr "  ABS_PATH (%s, goto done);\n" n;
6042              | Device n ->
6043                  pr_args n;
6044                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6045              | Dev_or_Path n ->
6046                  pr_args n;
6047                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6048              | String n -> pr_args n
6049              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6050              | StringList n ->
6051                  pr_list_handling_code n;
6052              | DeviceList n ->
6053                  pr_list_handling_code n;
6054                  pr "  /* Ensure that each is a device,\n";
6055                  pr "   * and perform device name translation. */\n";
6056                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6057                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6058                  pr "  }\n";
6059              | Bool n -> pr "  %s = args.%s;\n" n n
6060              | Int n -> pr "  %s = args.%s;\n" n n
6061              | Int64 n -> pr "  %s = args.%s;\n" n n
6062              | FileIn _ | FileOut _ -> ()
6063            ) args;
6064            pr "\n"
6065       );
6066
6067
6068       (* this is used at least for do_equal *)
6069       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6070         (* Emit NEED_ROOT just once, even when there are two or
6071            more Pathname args *)
6072         pr "  NEED_ROOT (goto done);\n";
6073       );
6074
6075       (* Don't want to call the impl with any FileIn or FileOut
6076        * parameters, since these go "outside" the RPC protocol.
6077        *)
6078       let args' =
6079         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6080           (snd style) in
6081       pr "  r = do_%s " name;
6082       generate_c_call_args (fst style, args');
6083       pr ";\n";
6084
6085       (match fst style with
6086        | RErr | RInt _ | RInt64 _ | RBool _
6087        | RConstString _ | RConstOptString _
6088        | RString _ | RStringList _ | RHashtable _
6089        | RStruct (_, _) | RStructList (_, _) ->
6090            pr "  if (r == %s)\n" error_code;
6091            pr "    /* do_%s has already called reply_with_error */\n" name;
6092            pr "    goto done;\n";
6093            pr "\n"
6094        | RBufferOut _ ->
6095            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6096            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6097            pr "   */\n";
6098            pr "  if (size == 1 && r == %s)\n" error_code;
6099            pr "    /* do_%s has already called reply_with_error */\n" name;
6100            pr "    goto done;\n";
6101            pr "\n"
6102       );
6103
6104       (* If there are any FileOut parameters, then the impl must
6105        * send its own reply.
6106        *)
6107       let no_reply =
6108         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6109       if no_reply then
6110         pr "  /* do_%s has already sent a reply */\n" name
6111       else (
6112         match fst style with
6113         | RErr -> pr "  reply (NULL, NULL);\n"
6114         | RInt n | RInt64 n | RBool n ->
6115             pr "  struct guestfs_%s_ret ret;\n" name;
6116             pr "  ret.%s = r;\n" n;
6117             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6118               name
6119         | RConstString _ | RConstOptString _ ->
6120             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6121         | RString n ->
6122             pr "  struct guestfs_%s_ret ret;\n" name;
6123             pr "  ret.%s = r;\n" n;
6124             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6125               name;
6126             pr "  free (r);\n"
6127         | RStringList n | RHashtable n ->
6128             pr "  struct guestfs_%s_ret ret;\n" name;
6129             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6130             pr "  ret.%s.%s_val = r;\n" n n;
6131             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6132               name;
6133             pr "  free_strings (r);\n"
6134         | RStruct (n, _) ->
6135             pr "  struct guestfs_%s_ret ret;\n" name;
6136             pr "  ret.%s = *r;\n" n;
6137             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6138               name;
6139             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6140               name
6141         | RStructList (n, _) ->
6142             pr "  struct guestfs_%s_ret ret;\n" name;
6143             pr "  ret.%s = *r;\n" n;
6144             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6145               name;
6146             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6147               name
6148         | RBufferOut n ->
6149             pr "  struct guestfs_%s_ret ret;\n" name;
6150             pr "  ret.%s.%s_val = r;\n" n n;
6151             pr "  ret.%s.%s_len = size;\n" n n;
6152             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6153               name;
6154             pr "  free (r);\n"
6155       );
6156
6157       (* Free the args. *)
6158       (match snd style with
6159        | [] ->
6160            pr "done: ;\n";
6161        | _ ->
6162            pr "done:\n";
6163            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6164              name
6165       );
6166
6167       pr "}\n\n";
6168   ) daemon_functions;
6169
6170   (* Dispatch function. *)
6171   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6172   pr "{\n";
6173   pr "  switch (proc_nr) {\n";
6174
6175   List.iter (
6176     fun (name, style, _, _, _, _, _) ->
6177       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6178       pr "      %s_stub (xdr_in);\n" name;
6179       pr "      break;\n"
6180   ) daemon_functions;
6181
6182   pr "    default:\n";
6183   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";
6184   pr "  }\n";
6185   pr "}\n";
6186   pr "\n";
6187
6188   (* LVM columns and tokenization functions. *)
6189   (* XXX This generates crap code.  We should rethink how we
6190    * do this parsing.
6191    *)
6192   List.iter (
6193     function
6194     | typ, cols ->
6195         pr "static const char *lvm_%s_cols = \"%s\";\n"
6196           typ (String.concat "," (List.map fst cols));
6197         pr "\n";
6198
6199         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6200         pr "{\n";
6201         pr "  char *tok, *p, *next;\n";
6202         pr "  int i, j;\n";
6203         pr "\n";
6204         (*
6205           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6206           pr "\n";
6207         *)
6208         pr "  if (!str) {\n";
6209         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6210         pr "    return -1;\n";
6211         pr "  }\n";
6212         pr "  if (!*str || c_isspace (*str)) {\n";
6213         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6214         pr "    return -1;\n";
6215         pr "  }\n";
6216         pr "  tok = str;\n";
6217         List.iter (
6218           fun (name, coltype) ->
6219             pr "  if (!tok) {\n";
6220             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6221             pr "    return -1;\n";
6222             pr "  }\n";
6223             pr "  p = strchrnul (tok, ',');\n";
6224             pr "  if (*p) next = p+1; else next = NULL;\n";
6225             pr "  *p = '\\0';\n";
6226             (match coltype with
6227              | FString ->
6228                  pr "  r->%s = strdup (tok);\n" name;
6229                  pr "  if (r->%s == NULL) {\n" name;
6230                  pr "    perror (\"strdup\");\n";
6231                  pr "    return -1;\n";
6232                  pr "  }\n"
6233              | FUUID ->
6234                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6235                  pr "    if (tok[j] == '\\0') {\n";
6236                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6237                  pr "      return -1;\n";
6238                  pr "    } else if (tok[j] != '-')\n";
6239                  pr "      r->%s[i++] = tok[j];\n" name;
6240                  pr "  }\n";
6241              | FBytes ->
6242                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6243                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6244                  pr "    return -1;\n";
6245                  pr "  }\n";
6246              | FInt64 ->
6247                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6248                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6249                  pr "    return -1;\n";
6250                  pr "  }\n";
6251              | FOptPercent ->
6252                  pr "  if (tok[0] == '\\0')\n";
6253                  pr "    r->%s = -1;\n" name;
6254                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6255                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6256                  pr "    return -1;\n";
6257                  pr "  }\n";
6258              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6259                  assert false (* can never be an LVM column *)
6260             );
6261             pr "  tok = next;\n";
6262         ) cols;
6263
6264         pr "  if (tok != NULL) {\n";
6265         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6266         pr "    return -1;\n";
6267         pr "  }\n";
6268         pr "  return 0;\n";
6269         pr "}\n";
6270         pr "\n";
6271
6272         pr "guestfs_int_lvm_%s_list *\n" typ;
6273         pr "parse_command_line_%ss (void)\n" typ;
6274         pr "{\n";
6275         pr "  char *out, *err;\n";
6276         pr "  char *p, *pend;\n";
6277         pr "  int r, i;\n";
6278         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6279         pr "  void *newp;\n";
6280         pr "\n";
6281         pr "  ret = malloc (sizeof *ret);\n";
6282         pr "  if (!ret) {\n";
6283         pr "    reply_with_perror (\"malloc\");\n";
6284         pr "    return NULL;\n";
6285         pr "  }\n";
6286         pr "\n";
6287         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6288         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6289         pr "\n";
6290         pr "  r = command (&out, &err,\n";
6291         pr "           \"lvm\", \"%ss\",\n" typ;
6292         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6293         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6294         pr "  if (r == -1) {\n";
6295         pr "    reply_with_error (\"%%s\", err);\n";
6296         pr "    free (out);\n";
6297         pr "    free (err);\n";
6298         pr "    free (ret);\n";
6299         pr "    return NULL;\n";
6300         pr "  }\n";
6301         pr "\n";
6302         pr "  free (err);\n";
6303         pr "\n";
6304         pr "  /* Tokenize each line of the output. */\n";
6305         pr "  p = out;\n";
6306         pr "  i = 0;\n";
6307         pr "  while (p) {\n";
6308         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6309         pr "    if (pend) {\n";
6310         pr "      *pend = '\\0';\n";
6311         pr "      pend++;\n";
6312         pr "    }\n";
6313         pr "\n";
6314         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6315         pr "      p++;\n";
6316         pr "\n";
6317         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6318         pr "      p = pend;\n";
6319         pr "      continue;\n";
6320         pr "    }\n";
6321         pr "\n";
6322         pr "    /* Allocate some space to store this next entry. */\n";
6323         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6324         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6325         pr "    if (newp == NULL) {\n";
6326         pr "      reply_with_perror (\"realloc\");\n";
6327         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6328         pr "      free (ret);\n";
6329         pr "      free (out);\n";
6330         pr "      return NULL;\n";
6331         pr "    }\n";
6332         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6333         pr "\n";
6334         pr "    /* Tokenize the next entry. */\n";
6335         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6336         pr "    if (r == -1) {\n";
6337         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6338         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6339         pr "      free (ret);\n";
6340         pr "      free (out);\n";
6341         pr "      return NULL;\n";
6342         pr "    }\n";
6343         pr "\n";
6344         pr "    ++i;\n";
6345         pr "    p = pend;\n";
6346         pr "  }\n";
6347         pr "\n";
6348         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6349         pr "\n";
6350         pr "  free (out);\n";
6351         pr "  return ret;\n";
6352         pr "}\n"
6353
6354   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6355
6356 (* Generate a list of function names, for debugging in the daemon.. *)
6357 and generate_daemon_names () =
6358   generate_header CStyle GPLv2plus;
6359
6360   pr "#include <config.h>\n";
6361   pr "\n";
6362   pr "#include \"daemon.h\"\n";
6363   pr "\n";
6364
6365   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6366   pr "const char *function_names[] = {\n";
6367   List.iter (
6368     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6369   ) daemon_functions;
6370   pr "};\n";
6371
6372 (* Generate the optional groups for the daemon to implement
6373  * guestfs_available.
6374  *)
6375 and generate_daemon_optgroups_c () =
6376   generate_header CStyle GPLv2plus;
6377
6378   pr "#include <config.h>\n";
6379   pr "\n";
6380   pr "#include \"daemon.h\"\n";
6381   pr "#include \"optgroups.h\"\n";
6382   pr "\n";
6383
6384   pr "struct optgroup optgroups[] = {\n";
6385   List.iter (
6386     fun (group, _) ->
6387       pr "  { \"%s\", optgroup_%s_available },\n" group group
6388   ) optgroups;
6389   pr "  { NULL, NULL }\n";
6390   pr "};\n"
6391
6392 and generate_daemon_optgroups_h () =
6393   generate_header CStyle GPLv2plus;
6394
6395   List.iter (
6396     fun (group, _) ->
6397       pr "extern int optgroup_%s_available (void);\n" group
6398   ) optgroups
6399
6400 (* Generate the tests. *)
6401 and generate_tests () =
6402   generate_header CStyle GPLv2plus;
6403
6404   pr "\
6405 #include <stdio.h>
6406 #include <stdlib.h>
6407 #include <string.h>
6408 #include <unistd.h>
6409 #include <sys/types.h>
6410 #include <fcntl.h>
6411
6412 #include \"guestfs.h\"
6413 #include \"guestfs-internal.h\"
6414
6415 static guestfs_h *g;
6416 static int suppress_error = 0;
6417
6418 static void print_error (guestfs_h *g, void *data, const char *msg)
6419 {
6420   if (!suppress_error)
6421     fprintf (stderr, \"%%s\\n\", msg);
6422 }
6423
6424 /* FIXME: nearly identical code appears in fish.c */
6425 static void print_strings (char *const *argv)
6426 {
6427   int argc;
6428
6429   for (argc = 0; argv[argc] != NULL; ++argc)
6430     printf (\"\\t%%s\\n\", argv[argc]);
6431 }
6432
6433 /*
6434 static void print_table (char const *const *argv)
6435 {
6436   int i;
6437
6438   for (i = 0; argv[i] != NULL; i += 2)
6439     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6440 }
6441 */
6442
6443 ";
6444
6445   (* Generate a list of commands which are not tested anywhere. *)
6446   pr "static void no_test_warnings (void)\n";
6447   pr "{\n";
6448
6449   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6450   List.iter (
6451     fun (_, _, _, _, tests, _, _) ->
6452       let tests = filter_map (
6453         function
6454         | (_, (Always|If _|Unless _), test) -> Some test
6455         | (_, Disabled, _) -> None
6456       ) tests in
6457       let seq = List.concat (List.map seq_of_test tests) in
6458       let cmds_tested = List.map List.hd seq in
6459       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6460   ) all_functions;
6461
6462   List.iter (
6463     fun (name, _, _, _, _, _, _) ->
6464       if not (Hashtbl.mem hash name) then
6465         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6466   ) all_functions;
6467
6468   pr "}\n";
6469   pr "\n";
6470
6471   (* Generate the actual tests.  Note that we generate the tests
6472    * in reverse order, deliberately, so that (in general) the
6473    * newest tests run first.  This makes it quicker and easier to
6474    * debug them.
6475    *)
6476   let test_names =
6477     List.map (
6478       fun (name, _, _, flags, tests, _, _) ->
6479         mapi (generate_one_test name flags) tests
6480     ) (List.rev all_functions) in
6481   let test_names = List.concat test_names in
6482   let nr_tests = List.length test_names in
6483
6484   pr "\
6485 int main (int argc, char *argv[])
6486 {
6487   char c = 0;
6488   unsigned long int n_failed = 0;
6489   const char *filename;
6490   int fd;
6491   int nr_tests, test_num = 0;
6492
6493   setbuf (stdout, NULL);
6494
6495   no_test_warnings ();
6496
6497   g = guestfs_create ();
6498   if (g == NULL) {
6499     printf (\"guestfs_create FAILED\\n\");
6500     exit (EXIT_FAILURE);
6501   }
6502
6503   guestfs_set_error_handler (g, print_error, NULL);
6504
6505   guestfs_set_path (g, \"../appliance\");
6506
6507   filename = \"test1.img\";
6508   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6509   if (fd == -1) {
6510     perror (filename);
6511     exit (EXIT_FAILURE);
6512   }
6513   if (lseek (fd, %d, SEEK_SET) == -1) {
6514     perror (\"lseek\");
6515     close (fd);
6516     unlink (filename);
6517     exit (EXIT_FAILURE);
6518   }
6519   if (write (fd, &c, 1) == -1) {
6520     perror (\"write\");
6521     close (fd);
6522     unlink (filename);
6523     exit (EXIT_FAILURE);
6524   }
6525   if (close (fd) == -1) {
6526     perror (filename);
6527     unlink (filename);
6528     exit (EXIT_FAILURE);
6529   }
6530   if (guestfs_add_drive (g, filename) == -1) {
6531     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6532     exit (EXIT_FAILURE);
6533   }
6534
6535   filename = \"test2.img\";
6536   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6537   if (fd == -1) {
6538     perror (filename);
6539     exit (EXIT_FAILURE);
6540   }
6541   if (lseek (fd, %d, SEEK_SET) == -1) {
6542     perror (\"lseek\");
6543     close (fd);
6544     unlink (filename);
6545     exit (EXIT_FAILURE);
6546   }
6547   if (write (fd, &c, 1) == -1) {
6548     perror (\"write\");
6549     close (fd);
6550     unlink (filename);
6551     exit (EXIT_FAILURE);
6552   }
6553   if (close (fd) == -1) {
6554     perror (filename);
6555     unlink (filename);
6556     exit (EXIT_FAILURE);
6557   }
6558   if (guestfs_add_drive (g, filename) == -1) {
6559     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6560     exit (EXIT_FAILURE);
6561   }
6562
6563   filename = \"test3.img\";
6564   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6565   if (fd == -1) {
6566     perror (filename);
6567     exit (EXIT_FAILURE);
6568   }
6569   if (lseek (fd, %d, SEEK_SET) == -1) {
6570     perror (\"lseek\");
6571     close (fd);
6572     unlink (filename);
6573     exit (EXIT_FAILURE);
6574   }
6575   if (write (fd, &c, 1) == -1) {
6576     perror (\"write\");
6577     close (fd);
6578     unlink (filename);
6579     exit (EXIT_FAILURE);
6580   }
6581   if (close (fd) == -1) {
6582     perror (filename);
6583     unlink (filename);
6584     exit (EXIT_FAILURE);
6585   }
6586   if (guestfs_add_drive (g, filename) == -1) {
6587     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6588     exit (EXIT_FAILURE);
6589   }
6590
6591   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6592     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6593     exit (EXIT_FAILURE);
6594   }
6595
6596   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6597   alarm (600);
6598
6599   if (guestfs_launch (g) == -1) {
6600     printf (\"guestfs_launch FAILED\\n\");
6601     exit (EXIT_FAILURE);
6602   }
6603
6604   /* Cancel previous alarm. */
6605   alarm (0);
6606
6607   nr_tests = %d;
6608
6609 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6610
6611   iteri (
6612     fun i test_name ->
6613       pr "  test_num++;\n";
6614       pr "  if (guestfs_get_verbose (g))\n";
6615       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6616       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6617       pr "  if (%s () == -1) {\n" test_name;
6618       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6619       pr "    n_failed++;\n";
6620       pr "  }\n";
6621   ) test_names;
6622   pr "\n";
6623
6624   pr "  guestfs_close (g);\n";
6625   pr "  unlink (\"test1.img\");\n";
6626   pr "  unlink (\"test2.img\");\n";
6627   pr "  unlink (\"test3.img\");\n";
6628   pr "\n";
6629
6630   pr "  if (n_failed > 0) {\n";
6631   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6632   pr "    exit (EXIT_FAILURE);\n";
6633   pr "  }\n";
6634   pr "\n";
6635
6636   pr "  exit (EXIT_SUCCESS);\n";
6637   pr "}\n"
6638
6639 and generate_one_test name flags i (init, prereq, test) =
6640   let test_name = sprintf "test_%s_%d" name i in
6641
6642   pr "\
6643 static int %s_skip (void)
6644 {
6645   const char *str;
6646
6647   str = getenv (\"TEST_ONLY\");
6648   if (str)
6649     return strstr (str, \"%s\") == NULL;
6650   str = getenv (\"SKIP_%s\");
6651   if (str && STREQ (str, \"1\")) return 1;
6652   str = getenv (\"SKIP_TEST_%s\");
6653   if (str && STREQ (str, \"1\")) return 1;
6654   return 0;
6655 }
6656
6657 " test_name name (String.uppercase test_name) (String.uppercase name);
6658
6659   (match prereq with
6660    | Disabled | Always -> ()
6661    | If code | Unless code ->
6662        pr "static int %s_prereq (void)\n" test_name;
6663        pr "{\n";
6664        pr "  %s\n" code;
6665        pr "}\n";
6666        pr "\n";
6667   );
6668
6669   pr "\
6670 static int %s (void)
6671 {
6672   if (%s_skip ()) {
6673     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6674     return 0;
6675   }
6676
6677 " test_name test_name test_name;
6678
6679   (* Optional functions should only be tested if the relevant
6680    * support is available in the daemon.
6681    *)
6682   List.iter (
6683     function
6684     | Optional group ->
6685         pr "  {\n";
6686         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6687         pr "    int r;\n";
6688         pr "    suppress_error = 1;\n";
6689         pr "    r = guestfs_available (g, (char **) groups);\n";
6690         pr "    suppress_error = 0;\n";
6691         pr "    if (r == -1) {\n";
6692         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6693         pr "      return 0;\n";
6694         pr "    }\n";
6695         pr "  }\n";
6696     | _ -> ()
6697   ) flags;
6698
6699   (match prereq with
6700    | Disabled ->
6701        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6702    | If _ ->
6703        pr "  if (! %s_prereq ()) {\n" test_name;
6704        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6705        pr "    return 0;\n";
6706        pr "  }\n";
6707        pr "\n";
6708        generate_one_test_body name i test_name init test;
6709    | Unless _ ->
6710        pr "  if (%s_prereq ()) {\n" test_name;
6711        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6712        pr "    return 0;\n";
6713        pr "  }\n";
6714        pr "\n";
6715        generate_one_test_body name i test_name init test;
6716    | Always ->
6717        generate_one_test_body name i test_name init test
6718   );
6719
6720   pr "  return 0;\n";
6721   pr "}\n";
6722   pr "\n";
6723   test_name
6724
6725 and generate_one_test_body name i test_name init test =
6726   (match init with
6727    | InitNone (* XXX at some point, InitNone and InitEmpty became
6728                * folded together as the same thing.  Really we should
6729                * make InitNone do nothing at all, but the tests may
6730                * need to be checked to make sure this is OK.
6731                *)
6732    | InitEmpty ->
6733        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6734        List.iter (generate_test_command_call test_name)
6735          [["blockdev_setrw"; "/dev/sda"];
6736           ["umount_all"];
6737           ["lvm_remove_all"]]
6738    | InitPartition ->
6739        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6740        List.iter (generate_test_command_call test_name)
6741          [["blockdev_setrw"; "/dev/sda"];
6742           ["umount_all"];
6743           ["lvm_remove_all"];
6744           ["part_disk"; "/dev/sda"; "mbr"]]
6745    | InitBasicFS ->
6746        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6747        List.iter (generate_test_command_call test_name)
6748          [["blockdev_setrw"; "/dev/sda"];
6749           ["umount_all"];
6750           ["lvm_remove_all"];
6751           ["part_disk"; "/dev/sda"; "mbr"];
6752           ["mkfs"; "ext2"; "/dev/sda1"];
6753           ["mount_options"; ""; "/dev/sda1"; "/"]]
6754    | InitBasicFSonLVM ->
6755        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6756          test_name;
6757        List.iter (generate_test_command_call test_name)
6758          [["blockdev_setrw"; "/dev/sda"];
6759           ["umount_all"];
6760           ["lvm_remove_all"];
6761           ["part_disk"; "/dev/sda"; "mbr"];
6762           ["pvcreate"; "/dev/sda1"];
6763           ["vgcreate"; "VG"; "/dev/sda1"];
6764           ["lvcreate"; "LV"; "VG"; "8"];
6765           ["mkfs"; "ext2"; "/dev/VG/LV"];
6766           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6767    | InitISOFS ->
6768        pr "  /* InitISOFS for %s */\n" test_name;
6769        List.iter (generate_test_command_call test_name)
6770          [["blockdev_setrw"; "/dev/sda"];
6771           ["umount_all"];
6772           ["lvm_remove_all"];
6773           ["mount_ro"; "/dev/sdd"; "/"]]
6774   );
6775
6776   let get_seq_last = function
6777     | [] ->
6778         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6779           test_name
6780     | seq ->
6781         let seq = List.rev seq in
6782         List.rev (List.tl seq), List.hd seq
6783   in
6784
6785   match test with
6786   | TestRun seq ->
6787       pr "  /* TestRun for %s (%d) */\n" name i;
6788       List.iter (generate_test_command_call test_name) seq
6789   | TestOutput (seq, expected) ->
6790       pr "  /* TestOutput for %s (%d) */\n" name i;
6791       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6792       let seq, last = get_seq_last seq in
6793       let test () =
6794         pr "    if (STRNEQ (r, expected)) {\n";
6795         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6796         pr "      return -1;\n";
6797         pr "    }\n"
6798       in
6799       List.iter (generate_test_command_call test_name) seq;
6800       generate_test_command_call ~test test_name last
6801   | TestOutputList (seq, expected) ->
6802       pr "  /* TestOutputList for %s (%d) */\n" name i;
6803       let seq, last = get_seq_last seq in
6804       let test () =
6805         iteri (
6806           fun i str ->
6807             pr "    if (!r[%d]) {\n" i;
6808             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6809             pr "      print_strings (r);\n";
6810             pr "      return -1;\n";
6811             pr "    }\n";
6812             pr "    {\n";
6813             pr "      const char *expected = \"%s\";\n" (c_quote str);
6814             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6815             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6816             pr "        return -1;\n";
6817             pr "      }\n";
6818             pr "    }\n"
6819         ) expected;
6820         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6821         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6822           test_name;
6823         pr "      print_strings (r);\n";
6824         pr "      return -1;\n";
6825         pr "    }\n"
6826       in
6827       List.iter (generate_test_command_call test_name) seq;
6828       generate_test_command_call ~test test_name last
6829   | TestOutputListOfDevices (seq, expected) ->
6830       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6831       let seq, last = get_seq_last seq in
6832       let test () =
6833         iteri (
6834           fun i str ->
6835             pr "    if (!r[%d]) {\n" i;
6836             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6837             pr "      print_strings (r);\n";
6838             pr "      return -1;\n";
6839             pr "    }\n";
6840             pr "    {\n";
6841             pr "      const char *expected = \"%s\";\n" (c_quote str);
6842             pr "      r[%d][5] = 's';\n" i;
6843             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6844             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6845             pr "        return -1;\n";
6846             pr "      }\n";
6847             pr "    }\n"
6848         ) expected;
6849         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6850         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6851           test_name;
6852         pr "      print_strings (r);\n";
6853         pr "      return -1;\n";
6854         pr "    }\n"
6855       in
6856       List.iter (generate_test_command_call test_name) seq;
6857       generate_test_command_call ~test test_name last
6858   | TestOutputInt (seq, expected) ->
6859       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6860       let seq, last = get_seq_last seq in
6861       let test () =
6862         pr "    if (r != %d) {\n" expected;
6863         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6864           test_name expected;
6865         pr "               (int) r);\n";
6866         pr "      return -1;\n";
6867         pr "    }\n"
6868       in
6869       List.iter (generate_test_command_call test_name) seq;
6870       generate_test_command_call ~test test_name last
6871   | TestOutputIntOp (seq, op, expected) ->
6872       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6873       let seq, last = get_seq_last seq in
6874       let test () =
6875         pr "    if (! (r %s %d)) {\n" op expected;
6876         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6877           test_name op expected;
6878         pr "               (int) r);\n";
6879         pr "      return -1;\n";
6880         pr "    }\n"
6881       in
6882       List.iter (generate_test_command_call test_name) seq;
6883       generate_test_command_call ~test test_name last
6884   | TestOutputTrue seq ->
6885       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6886       let seq, last = get_seq_last seq in
6887       let test () =
6888         pr "    if (!r) {\n";
6889         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6890           test_name;
6891         pr "      return -1;\n";
6892         pr "    }\n"
6893       in
6894       List.iter (generate_test_command_call test_name) seq;
6895       generate_test_command_call ~test test_name last
6896   | TestOutputFalse seq ->
6897       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6898       let seq, last = get_seq_last seq in
6899       let test () =
6900         pr "    if (r) {\n";
6901         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6902           test_name;
6903         pr "      return -1;\n";
6904         pr "    }\n"
6905       in
6906       List.iter (generate_test_command_call test_name) seq;
6907       generate_test_command_call ~test test_name last
6908   | TestOutputLength (seq, expected) ->
6909       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6910       let seq, last = get_seq_last seq in
6911       let test () =
6912         pr "    int j;\n";
6913         pr "    for (j = 0; j < %d; ++j)\n" expected;
6914         pr "      if (r[j] == NULL) {\n";
6915         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6916           test_name;
6917         pr "        print_strings (r);\n";
6918         pr "        return -1;\n";
6919         pr "      }\n";
6920         pr "    if (r[j] != NULL) {\n";
6921         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6922           test_name;
6923         pr "      print_strings (r);\n";
6924         pr "      return -1;\n";
6925         pr "    }\n"
6926       in
6927       List.iter (generate_test_command_call test_name) seq;
6928       generate_test_command_call ~test test_name last
6929   | TestOutputBuffer (seq, expected) ->
6930       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6931       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6932       let seq, last = get_seq_last seq in
6933       let len = String.length expected in
6934       let test () =
6935         pr "    if (size != %d) {\n" len;
6936         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6937         pr "      return -1;\n";
6938         pr "    }\n";
6939         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6940         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6941         pr "      return -1;\n";
6942         pr "    }\n"
6943       in
6944       List.iter (generate_test_command_call test_name) seq;
6945       generate_test_command_call ~test test_name last
6946   | TestOutputStruct (seq, checks) ->
6947       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6948       let seq, last = get_seq_last seq in
6949       let test () =
6950         List.iter (
6951           function
6952           | CompareWithInt (field, expected) ->
6953               pr "    if (r->%s != %d) {\n" field expected;
6954               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6955                 test_name field expected;
6956               pr "               (int) r->%s);\n" field;
6957               pr "      return -1;\n";
6958               pr "    }\n"
6959           | CompareWithIntOp (field, op, expected) ->
6960               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6961               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6962                 test_name field op expected;
6963               pr "               (int) r->%s);\n" field;
6964               pr "      return -1;\n";
6965               pr "    }\n"
6966           | CompareWithString (field, expected) ->
6967               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6968               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6969                 test_name field expected;
6970               pr "               r->%s);\n" field;
6971               pr "      return -1;\n";
6972               pr "    }\n"
6973           | CompareFieldsIntEq (field1, field2) ->
6974               pr "    if (r->%s != r->%s) {\n" field1 field2;
6975               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6976                 test_name field1 field2;
6977               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6978               pr "      return -1;\n";
6979               pr "    }\n"
6980           | CompareFieldsStrEq (field1, field2) ->
6981               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6982               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6983                 test_name field1 field2;
6984               pr "               r->%s, r->%s);\n" field1 field2;
6985               pr "      return -1;\n";
6986               pr "    }\n"
6987         ) checks
6988       in
6989       List.iter (generate_test_command_call test_name) seq;
6990       generate_test_command_call ~test test_name last
6991   | TestLastFail seq ->
6992       pr "  /* TestLastFail for %s (%d) */\n" name i;
6993       let seq, last = get_seq_last seq in
6994       List.iter (generate_test_command_call test_name) seq;
6995       generate_test_command_call test_name ~expect_error:true last
6996
6997 (* Generate the code to run a command, leaving the result in 'r'.
6998  * If you expect to get an error then you should set expect_error:true.
6999  *)
7000 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7001   match cmd with
7002   | [] -> assert false
7003   | name :: args ->
7004       (* Look up the command to find out what args/ret it has. *)
7005       let style =
7006         try
7007           let _, style, _, _, _, _, _ =
7008             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7009           style
7010         with Not_found ->
7011           failwithf "%s: in test, command %s was not found" test_name name in
7012
7013       if List.length (snd style) <> List.length args then
7014         failwithf "%s: in test, wrong number of args given to %s"
7015           test_name name;
7016
7017       pr "  {\n";
7018
7019       List.iter (
7020         function
7021         | OptString n, "NULL" -> ()
7022         | Pathname n, arg
7023         | Device n, arg
7024         | Dev_or_Path n, arg
7025         | String n, arg
7026         | OptString n, arg ->
7027             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7028         | Int _, _
7029         | Int64 _, _
7030         | Bool _, _
7031         | FileIn _, _ | FileOut _, _ -> ()
7032         | StringList n, "" | DeviceList n, "" ->
7033             pr "    const char *const %s[1] = { NULL };\n" n
7034         | StringList n, arg | DeviceList n, arg ->
7035             let strs = string_split " " arg in
7036             iteri (
7037               fun i str ->
7038                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7039             ) strs;
7040             pr "    const char *const %s[] = {\n" n;
7041             iteri (
7042               fun i _ -> pr "      %s_%d,\n" n i
7043             ) strs;
7044             pr "      NULL\n";
7045             pr "    };\n";
7046       ) (List.combine (snd style) args);
7047
7048       let error_code =
7049         match fst style with
7050         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7051         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7052         | RConstString _ | RConstOptString _ ->
7053             pr "    const char *r;\n"; "NULL"
7054         | RString _ -> pr "    char *r;\n"; "NULL"
7055         | RStringList _ | RHashtable _ ->
7056             pr "    char **r;\n";
7057             pr "    int i;\n";
7058             "NULL"
7059         | RStruct (_, typ) ->
7060             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7061         | RStructList (_, typ) ->
7062             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7063         | RBufferOut _ ->
7064             pr "    char *r;\n";
7065             pr "    size_t size;\n";
7066             "NULL" in
7067
7068       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7069       pr "    r = guestfs_%s (g" name;
7070
7071       (* Generate the parameters. *)
7072       List.iter (
7073         function
7074         | OptString _, "NULL" -> pr ", NULL"
7075         | Pathname n, _
7076         | Device n, _ | Dev_or_Path n, _
7077         | String n, _
7078         | OptString n, _ ->
7079             pr ", %s" n
7080         | FileIn _, arg | FileOut _, arg ->
7081             pr ", \"%s\"" (c_quote arg)
7082         | StringList n, _ | DeviceList n, _ ->
7083             pr ", (char **) %s" n
7084         | Int _, arg ->
7085             let i =
7086               try int_of_string arg
7087               with Failure "int_of_string" ->
7088                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7089             pr ", %d" i
7090         | Int64 _, arg ->
7091             let i =
7092               try Int64.of_string arg
7093               with Failure "int_of_string" ->
7094                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7095             pr ", %Ld" i
7096         | Bool _, arg ->
7097             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7098       ) (List.combine (snd style) args);
7099
7100       (match fst style with
7101        | RBufferOut _ -> pr ", &size"
7102        | _ -> ()
7103       );
7104
7105       pr ");\n";
7106
7107       if not expect_error then
7108         pr "    if (r == %s)\n" error_code
7109       else
7110         pr "    if (r != %s)\n" error_code;
7111       pr "      return -1;\n";
7112
7113       (* Insert the test code. *)
7114       (match test with
7115        | None -> ()
7116        | Some f -> f ()
7117       );
7118
7119       (match fst style with
7120        | RErr | RInt _ | RInt64 _ | RBool _
7121        | RConstString _ | RConstOptString _ -> ()
7122        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7123        | RStringList _ | RHashtable _ ->
7124            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7125            pr "      free (r[i]);\n";
7126            pr "    free (r);\n"
7127        | RStruct (_, typ) ->
7128            pr "    guestfs_free_%s (r);\n" typ
7129        | RStructList (_, typ) ->
7130            pr "    guestfs_free_%s_list (r);\n" typ
7131       );
7132
7133       pr "  }\n"
7134
7135 and c_quote str =
7136   let str = replace_str str "\r" "\\r" in
7137   let str = replace_str str "\n" "\\n" in
7138   let str = replace_str str "\t" "\\t" in
7139   let str = replace_str str "\000" "\\0" in
7140   str
7141
7142 (* Generate a lot of different functions for guestfish. *)
7143 and generate_fish_cmds () =
7144   generate_header CStyle GPLv2plus;
7145
7146   let all_functions =
7147     List.filter (
7148       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7149     ) all_functions in
7150   let all_functions_sorted =
7151     List.filter (
7152       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7153     ) all_functions_sorted in
7154
7155   pr "#include <config.h>\n";
7156   pr "\n";
7157   pr "#include <stdio.h>\n";
7158   pr "#include <stdlib.h>\n";
7159   pr "#include <string.h>\n";
7160   pr "#include <inttypes.h>\n";
7161   pr "\n";
7162   pr "#include <guestfs.h>\n";
7163   pr "#include \"c-ctype.h\"\n";
7164   pr "#include \"full-write.h\"\n";
7165   pr "#include \"xstrtol.h\"\n";
7166   pr "#include \"fish.h\"\n";
7167   pr "\n";
7168
7169   (* list_commands function, which implements guestfish -h *)
7170   pr "void list_commands (void)\n";
7171   pr "{\n";
7172   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7173   pr "  list_builtin_commands ();\n";
7174   List.iter (
7175     fun (name, _, _, flags, _, shortdesc, _) ->
7176       let name = replace_char name '_' '-' in
7177       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7178         name shortdesc
7179   ) all_functions_sorted;
7180   pr "  printf (\"    %%s\\n\",";
7181   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7182   pr "}\n";
7183   pr "\n";
7184
7185   (* display_command function, which implements guestfish -h cmd *)
7186   pr "void display_command (const char *cmd)\n";
7187   pr "{\n";
7188   List.iter (
7189     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7190       let name2 = replace_char name '_' '-' in
7191       let alias =
7192         try find_map (function FishAlias n -> Some n | _ -> None) flags
7193         with Not_found -> name in
7194       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7195       let synopsis =
7196         match snd style with
7197         | [] -> name2
7198         | args ->
7199             sprintf "%s %s"
7200               name2 (String.concat " " (List.map name_of_argt args)) in
7201
7202       let warnings =
7203         if List.mem ProtocolLimitWarning flags then
7204           ("\n\n" ^ protocol_limit_warning)
7205         else "" in
7206
7207       (* For DangerWillRobinson commands, we should probably have
7208        * guestfish prompt before allowing you to use them (especially
7209        * in interactive mode). XXX
7210        *)
7211       let warnings =
7212         warnings ^
7213           if List.mem DangerWillRobinson flags then
7214             ("\n\n" ^ danger_will_robinson)
7215           else "" in
7216
7217       let warnings =
7218         warnings ^
7219           match deprecation_notice flags with
7220           | None -> ""
7221           | Some txt -> "\n\n" ^ txt in
7222
7223       let describe_alias =
7224         if name <> alias then
7225           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7226         else "" in
7227
7228       pr "  if (";
7229       pr "STRCASEEQ (cmd, \"%s\")" name;
7230       if name <> name2 then
7231         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7232       if name <> alias then
7233         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7234       pr ")\n";
7235       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7236         name2 shortdesc
7237         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7238          "=head1 DESCRIPTION\n\n" ^
7239          longdesc ^ warnings ^ describe_alias);
7240       pr "  else\n"
7241   ) all_functions;
7242   pr "    display_builtin_command (cmd);\n";
7243   pr "}\n";
7244   pr "\n";
7245
7246   let emit_print_list_function typ =
7247     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7248       typ typ typ;
7249     pr "{\n";
7250     pr "  unsigned int i;\n";
7251     pr "\n";
7252     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7253     pr "    printf (\"[%%d] = {\\n\", i);\n";
7254     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7255     pr "    printf (\"}\\n\");\n";
7256     pr "  }\n";
7257     pr "}\n";
7258     pr "\n";
7259   in
7260
7261   (* print_* functions *)
7262   List.iter (
7263     fun (typ, cols) ->
7264       let needs_i =
7265         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7266
7267       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7268       pr "{\n";
7269       if needs_i then (
7270         pr "  unsigned int i;\n";
7271         pr "\n"
7272       );
7273       List.iter (
7274         function
7275         | name, FString ->
7276             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7277         | name, FUUID ->
7278             pr "  printf (\"%%s%s: \", indent);\n" name;
7279             pr "  for (i = 0; i < 32; ++i)\n";
7280             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7281             pr "  printf (\"\\n\");\n"
7282         | name, FBuffer ->
7283             pr "  printf (\"%%s%s: \", indent);\n" name;
7284             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7285             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7286             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7287             pr "    else\n";
7288             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7289             pr "  printf (\"\\n\");\n"
7290         | name, (FUInt64|FBytes) ->
7291             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7292               name typ name
7293         | name, FInt64 ->
7294             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7295               name typ name
7296         | name, FUInt32 ->
7297             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7298               name typ name
7299         | name, FInt32 ->
7300             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7301               name typ name
7302         | name, FChar ->
7303             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7304               name typ name
7305         | name, FOptPercent ->
7306             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7307               typ name name typ name;
7308             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7309       ) cols;
7310       pr "}\n";
7311       pr "\n";
7312   ) structs;
7313
7314   (* Emit a print_TYPE_list function definition only if that function is used. *)
7315   List.iter (
7316     function
7317     | typ, (RStructListOnly | RStructAndList) ->
7318         (* generate the function for typ *)
7319         emit_print_list_function typ
7320     | typ, _ -> () (* empty *)
7321   ) (rstructs_used_by all_functions);
7322
7323   (* Emit a print_TYPE function definition only if that function is used. *)
7324   List.iter (
7325     function
7326     | typ, (RStructOnly | RStructAndList) ->
7327         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7328         pr "{\n";
7329         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7330         pr "}\n";
7331         pr "\n";
7332     | typ, _ -> () (* empty *)
7333   ) (rstructs_used_by all_functions);
7334
7335   (* run_<action> actions *)
7336   List.iter (
7337     fun (name, style, _, flags, _, _, _) ->
7338       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7339       pr "{\n";
7340       (match fst style with
7341        | RErr
7342        | RInt _
7343        | RBool _ -> pr "  int r;\n"
7344        | RInt64 _ -> pr "  int64_t r;\n"
7345        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7346        | RString _ -> pr "  char *r;\n"
7347        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7348        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7349        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7350        | RBufferOut _ ->
7351            pr "  char *r;\n";
7352            pr "  size_t size;\n";
7353       );
7354       List.iter (
7355         function
7356         | Device n
7357         | String n
7358         | OptString n
7359         | FileIn n
7360         | FileOut n -> pr "  const char *%s;\n" n
7361         | Pathname n
7362         | Dev_or_Path n -> pr "  char *%s;\n" n
7363         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7364         | Bool n -> pr "  int %s;\n" n
7365         | Int n -> pr "  int %s;\n" n
7366         | Int64 n -> pr "  int64_t %s;\n" n
7367       ) (snd style);
7368
7369       (* Check and convert parameters. *)
7370       let argc_expected = List.length (snd style) in
7371       pr "  if (argc != %d) {\n" argc_expected;
7372       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7373         argc_expected;
7374       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7375       pr "    return -1;\n";
7376       pr "  }\n";
7377
7378       let parse_integer fn fntyp rtyp range name i =
7379         pr "  {\n";
7380         pr "    strtol_error xerr;\n";
7381         pr "    %s r;\n" fntyp;
7382         pr "\n";
7383         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7384         pr "    if (xerr != LONGINT_OK) {\n";
7385         pr "      fprintf (stderr,\n";
7386         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7387         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7388         pr "      return -1;\n";
7389         pr "    }\n";
7390         (match range with
7391          | None -> ()
7392          | Some (min, max, comment) ->
7393              pr "    /* %s */\n" comment;
7394              pr "    if (r < %s || r > %s) {\n" min max;
7395              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7396                name;
7397              pr "      return -1;\n";
7398              pr "    }\n";
7399              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7400         );
7401         pr "    %s = r;\n" name;
7402         pr "  }\n";
7403       in
7404
7405       iteri (
7406         fun i ->
7407           function
7408           | Device name
7409           | String name ->
7410               pr "  %s = argv[%d];\n" name i
7411           | Pathname name
7412           | Dev_or_Path name ->
7413               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7414               pr "  if (%s == NULL) return -1;\n" name
7415           | OptString name ->
7416               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7417                 name i i
7418           | FileIn name ->
7419               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7420                 name i i
7421           | FileOut name ->
7422               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7423                 name i i
7424           | StringList name | DeviceList name ->
7425               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7426               pr "  if (%s == NULL) return -1;\n" name;
7427           | Bool name ->
7428               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7429           | Int name ->
7430               let range =
7431                 let min = "(-(2LL<<30))"
7432                 and max = "((2LL<<30)-1)"
7433                 and comment =
7434                   "The Int type in the generator is a signed 31 bit int." in
7435                 Some (min, max, comment) in
7436               parse_integer "xstrtoll" "long long" "int" range name i
7437           | Int64 name ->
7438               parse_integer "xstrtoll" "long long" "int64_t" None name i
7439       ) (snd style);
7440
7441       (* Call C API function. *)
7442       let fn =
7443         try find_map (function FishAction n -> Some n | _ -> None) flags
7444         with Not_found -> sprintf "guestfs_%s" name in
7445       pr "  r = %s " fn;
7446       generate_c_call_args ~handle:"g" style;
7447       pr ";\n";
7448
7449       List.iter (
7450         function
7451         | Device name | String name
7452         | OptString name | FileIn name | FileOut name | Bool name
7453         | Int name | Int64 name -> ()
7454         | Pathname name | Dev_or_Path name ->
7455             pr "  free (%s);\n" name
7456         | StringList name | DeviceList name ->
7457             pr "  free_strings (%s);\n" name
7458       ) (snd style);
7459
7460       (* Check return value for errors and display command results. *)
7461       (match fst style with
7462        | RErr -> pr "  return r;\n"
7463        | RInt _ ->
7464            pr "  if (r == -1) return -1;\n";
7465            pr "  printf (\"%%d\\n\", r);\n";
7466            pr "  return 0;\n"
7467        | RInt64 _ ->
7468            pr "  if (r == -1) return -1;\n";
7469            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7470            pr "  return 0;\n"
7471        | RBool _ ->
7472            pr "  if (r == -1) return -1;\n";
7473            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7474            pr "  return 0;\n"
7475        | RConstString _ ->
7476            pr "  if (r == NULL) return -1;\n";
7477            pr "  printf (\"%%s\\n\", r);\n";
7478            pr "  return 0;\n"
7479        | RConstOptString _ ->
7480            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7481            pr "  return 0;\n"
7482        | RString _ ->
7483            pr "  if (r == NULL) return -1;\n";
7484            pr "  printf (\"%%s\\n\", r);\n";
7485            pr "  free (r);\n";
7486            pr "  return 0;\n"
7487        | RStringList _ ->
7488            pr "  if (r == NULL) return -1;\n";
7489            pr "  print_strings (r);\n";
7490            pr "  free_strings (r);\n";
7491            pr "  return 0;\n"
7492        | RStruct (_, typ) ->
7493            pr "  if (r == NULL) return -1;\n";
7494            pr "  print_%s (r);\n" typ;
7495            pr "  guestfs_free_%s (r);\n" typ;
7496            pr "  return 0;\n"
7497        | RStructList (_, typ) ->
7498            pr "  if (r == NULL) return -1;\n";
7499            pr "  print_%s_list (r);\n" typ;
7500            pr "  guestfs_free_%s_list (r);\n" typ;
7501            pr "  return 0;\n"
7502        | RHashtable _ ->
7503            pr "  if (r == NULL) return -1;\n";
7504            pr "  print_table (r);\n";
7505            pr "  free_strings (r);\n";
7506            pr "  return 0;\n"
7507        | RBufferOut _ ->
7508            pr "  if (r == NULL) return -1;\n";
7509            pr "  if (full_write (1, r, size) != size) {\n";
7510            pr "    perror (\"write\");\n";
7511            pr "    free (r);\n";
7512            pr "    return -1;\n";
7513            pr "  }\n";
7514            pr "  free (r);\n";
7515            pr "  return 0;\n"
7516       );
7517       pr "}\n";
7518       pr "\n"
7519   ) all_functions;
7520
7521   (* run_action function *)
7522   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7523   pr "{\n";
7524   List.iter (
7525     fun (name, _, _, flags, _, _, _) ->
7526       let name2 = replace_char name '_' '-' in
7527       let alias =
7528         try find_map (function FishAlias n -> Some n | _ -> None) flags
7529         with Not_found -> name in
7530       pr "  if (";
7531       pr "STRCASEEQ (cmd, \"%s\")" name;
7532       if name <> name2 then
7533         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7534       if name <> alias then
7535         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7536       pr ")\n";
7537       pr "    return run_%s (cmd, argc, argv);\n" name;
7538       pr "  else\n";
7539   ) all_functions;
7540   pr "    {\n";
7541   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7542   pr "      if (command_num == 1)\n";
7543   pr "        extended_help_message ();\n";
7544   pr "      return -1;\n";
7545   pr "    }\n";
7546   pr "  return 0;\n";
7547   pr "}\n";
7548   pr "\n"
7549
7550 (* Readline completion for guestfish. *)
7551 and generate_fish_completion () =
7552   generate_header CStyle GPLv2plus;
7553
7554   let all_functions =
7555     List.filter (
7556       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7557     ) all_functions in
7558
7559   pr "\
7560 #include <config.h>
7561
7562 #include <stdio.h>
7563 #include <stdlib.h>
7564 #include <string.h>
7565
7566 #ifdef HAVE_LIBREADLINE
7567 #include <readline/readline.h>
7568 #endif
7569
7570 #include \"fish.h\"
7571
7572 #ifdef HAVE_LIBREADLINE
7573
7574 static const char *const commands[] = {
7575   BUILTIN_COMMANDS_FOR_COMPLETION,
7576 ";
7577
7578   (* Get the commands, including the aliases.  They don't need to be
7579    * sorted - the generator() function just does a dumb linear search.
7580    *)
7581   let commands =
7582     List.map (
7583       fun (name, _, _, flags, _, _, _) ->
7584         let name2 = replace_char name '_' '-' in
7585         let alias =
7586           try find_map (function FishAlias n -> Some n | _ -> None) flags
7587           with Not_found -> name in
7588
7589         if name <> alias then [name2; alias] else [name2]
7590     ) all_functions in
7591   let commands = List.flatten commands in
7592
7593   List.iter (pr "  \"%s\",\n") commands;
7594
7595   pr "  NULL
7596 };
7597
7598 static char *
7599 generator (const char *text, int state)
7600 {
7601   static int index, len;
7602   const char *name;
7603
7604   if (!state) {
7605     index = 0;
7606     len = strlen (text);
7607   }
7608
7609   rl_attempted_completion_over = 1;
7610
7611   while ((name = commands[index]) != NULL) {
7612     index++;
7613     if (STRCASEEQLEN (name, text, len))
7614       return strdup (name);
7615   }
7616
7617   return NULL;
7618 }
7619
7620 #endif /* HAVE_LIBREADLINE */
7621
7622 #ifdef HAVE_RL_COMPLETION_MATCHES
7623 #define RL_COMPLETION_MATCHES rl_completion_matches
7624 #else
7625 #ifdef HAVE_COMPLETION_MATCHES
7626 #define RL_COMPLETION_MATCHES completion_matches
7627 #endif
7628 #endif /* else just fail if we don't have either symbol */
7629
7630 char **
7631 do_completion (const char *text, int start, int end)
7632 {
7633   char **matches = NULL;
7634
7635 #ifdef HAVE_LIBREADLINE
7636   rl_completion_append_character = ' ';
7637
7638   if (start == 0)
7639     matches = RL_COMPLETION_MATCHES (text, generator);
7640   else if (complete_dest_paths)
7641     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7642 #endif
7643
7644   return matches;
7645 }
7646 ";
7647
7648 (* Generate the POD documentation for guestfish. *)
7649 and generate_fish_actions_pod () =
7650   let all_functions_sorted =
7651     List.filter (
7652       fun (_, _, _, flags, _, _, _) ->
7653         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7654     ) all_functions_sorted in
7655
7656   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7657
7658   List.iter (
7659     fun (name, style, _, flags, _, _, longdesc) ->
7660       let longdesc =
7661         Str.global_substitute rex (
7662           fun s ->
7663             let sub =
7664               try Str.matched_group 1 s
7665               with Not_found ->
7666                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7667             "C<" ^ replace_char sub '_' '-' ^ ">"
7668         ) longdesc in
7669       let name = replace_char name '_' '-' in
7670       let alias =
7671         try find_map (function FishAlias n -> Some n | _ -> None) flags
7672         with Not_found -> name in
7673
7674       pr "=head2 %s" name;
7675       if name <> alias then
7676         pr " | %s" alias;
7677       pr "\n";
7678       pr "\n";
7679       pr " %s" name;
7680       List.iter (
7681         function
7682         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7683         | OptString n -> pr " %s" n
7684         | StringList n | DeviceList n -> pr " '%s ...'" n
7685         | Bool _ -> pr " true|false"
7686         | Int n -> pr " %s" n
7687         | Int64 n -> pr " %s" n
7688         | FileIn n | FileOut n -> pr " (%s|-)" n
7689       ) (snd style);
7690       pr "\n";
7691       pr "\n";
7692       pr "%s\n\n" longdesc;
7693
7694       if List.exists (function FileIn _ | FileOut _ -> true
7695                       | _ -> false) (snd style) then
7696         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7697
7698       if List.mem ProtocolLimitWarning flags then
7699         pr "%s\n\n" protocol_limit_warning;
7700
7701       if List.mem DangerWillRobinson flags then
7702         pr "%s\n\n" danger_will_robinson;
7703
7704       match deprecation_notice flags with
7705       | None -> ()
7706       | Some txt -> pr "%s\n\n" txt
7707   ) all_functions_sorted
7708
7709 (* Generate a C function prototype. *)
7710 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7711     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7712     ?(prefix = "")
7713     ?handle name style =
7714   if extern then pr "extern ";
7715   if static then pr "static ";
7716   (match fst style with
7717    | RErr -> pr "int "
7718    | RInt _ -> pr "int "
7719    | RInt64 _ -> pr "int64_t "
7720    | RBool _ -> pr "int "
7721    | RConstString _ | RConstOptString _ -> pr "const char *"
7722    | RString _ | RBufferOut _ -> pr "char *"
7723    | RStringList _ | RHashtable _ -> pr "char **"
7724    | RStruct (_, typ) ->
7725        if not in_daemon then pr "struct guestfs_%s *" typ
7726        else pr "guestfs_int_%s *" typ
7727    | RStructList (_, typ) ->
7728        if not in_daemon then pr "struct guestfs_%s_list *" typ
7729        else pr "guestfs_int_%s_list *" typ
7730   );
7731   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7732   pr "%s%s (" prefix name;
7733   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7734     pr "void"
7735   else (
7736     let comma = ref false in
7737     (match handle with
7738      | None -> ()
7739      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7740     );
7741     let next () =
7742       if !comma then (
7743         if single_line then pr ", " else pr ",\n\t\t"
7744       );
7745       comma := true
7746     in
7747     List.iter (
7748       function
7749       | Pathname n
7750       | Device n | Dev_or_Path n
7751       | String n
7752       | OptString n ->
7753           next ();
7754           pr "const char *%s" n
7755       | StringList n | DeviceList n ->
7756           next ();
7757           pr "char *const *%s" n
7758       | Bool n -> next (); pr "int %s" n
7759       | Int n -> next (); pr "int %s" n
7760       | Int64 n -> next (); pr "int64_t %s" n
7761       | FileIn n
7762       | FileOut n ->
7763           if not in_daemon then (next (); pr "const char *%s" n)
7764     ) (snd style);
7765     if is_RBufferOut then (next (); pr "size_t *size_r");
7766   );
7767   pr ")";
7768   if semicolon then pr ";";
7769   if newline then pr "\n"
7770
7771 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7772 and generate_c_call_args ?handle ?(decl = false) style =
7773   pr "(";
7774   let comma = ref false in
7775   let next () =
7776     if !comma then pr ", ";
7777     comma := true
7778   in
7779   (match handle with
7780    | None -> ()
7781    | Some handle -> pr "%s" handle; comma := true
7782   );
7783   List.iter (
7784     fun arg ->
7785       next ();
7786       pr "%s" (name_of_argt arg)
7787   ) (snd style);
7788   (* For RBufferOut calls, add implicit &size parameter. *)
7789   if not decl then (
7790     match fst style with
7791     | RBufferOut _ ->
7792         next ();
7793         pr "&size"
7794     | _ -> ()
7795   );
7796   pr ")"
7797
7798 (* Generate the OCaml bindings interface. *)
7799 and generate_ocaml_mli () =
7800   generate_header OCamlStyle LGPLv2plus;
7801
7802   pr "\
7803 (** For API documentation you should refer to the C API
7804     in the guestfs(3) manual page.  The OCaml API uses almost
7805     exactly the same calls. *)
7806
7807 type t
7808 (** A [guestfs_h] handle. *)
7809
7810 exception Error of string
7811 (** This exception is raised when there is an error. *)
7812
7813 exception Handle_closed of string
7814 (** This exception is raised if you use a {!Guestfs.t} handle
7815     after calling {!close} on it.  The string is the name of
7816     the function. *)
7817
7818 val create : unit -> t
7819 (** Create a {!Guestfs.t} handle. *)
7820
7821 val close : t -> unit
7822 (** Close the {!Guestfs.t} handle and free up all resources used
7823     by it immediately.
7824
7825     Handles are closed by the garbage collector when they become
7826     unreferenced, but callers can call this in order to provide
7827     predictable cleanup. *)
7828
7829 ";
7830   generate_ocaml_structure_decls ();
7831
7832   (* The actions. *)
7833   List.iter (
7834     fun (name, style, _, _, _, shortdesc, _) ->
7835       generate_ocaml_prototype name style;
7836       pr "(** %s *)\n" shortdesc;
7837       pr "\n"
7838   ) all_functions_sorted
7839
7840 (* Generate the OCaml bindings implementation. *)
7841 and generate_ocaml_ml () =
7842   generate_header OCamlStyle LGPLv2plus;
7843
7844   pr "\
7845 type t
7846
7847 exception Error of string
7848 exception Handle_closed of string
7849
7850 external create : unit -> t = \"ocaml_guestfs_create\"
7851 external close : t -> unit = \"ocaml_guestfs_close\"
7852
7853 (* Give the exceptions names, so they can be raised from the C code. *)
7854 let () =
7855   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7856   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7857
7858 ";
7859
7860   generate_ocaml_structure_decls ();
7861
7862   (* The actions. *)
7863   List.iter (
7864     fun (name, style, _, _, _, shortdesc, _) ->
7865       generate_ocaml_prototype ~is_external:true name style;
7866   ) all_functions_sorted
7867
7868 (* Generate the OCaml bindings C implementation. *)
7869 and generate_ocaml_c () =
7870   generate_header CStyle LGPLv2plus;
7871
7872   pr "\
7873 #include <stdio.h>
7874 #include <stdlib.h>
7875 #include <string.h>
7876
7877 #include <caml/config.h>
7878 #include <caml/alloc.h>
7879 #include <caml/callback.h>
7880 #include <caml/fail.h>
7881 #include <caml/memory.h>
7882 #include <caml/mlvalues.h>
7883 #include <caml/signals.h>
7884
7885 #include <guestfs.h>
7886
7887 #include \"guestfs_c.h\"
7888
7889 /* Copy a hashtable of string pairs into an assoc-list.  We return
7890  * the list in reverse order, but hashtables aren't supposed to be
7891  * ordered anyway.
7892  */
7893 static CAMLprim value
7894 copy_table (char * const * argv)
7895 {
7896   CAMLparam0 ();
7897   CAMLlocal5 (rv, pairv, kv, vv, cons);
7898   int i;
7899
7900   rv = Val_int (0);
7901   for (i = 0; argv[i] != NULL; i += 2) {
7902     kv = caml_copy_string (argv[i]);
7903     vv = caml_copy_string (argv[i+1]);
7904     pairv = caml_alloc (2, 0);
7905     Store_field (pairv, 0, kv);
7906     Store_field (pairv, 1, vv);
7907     cons = caml_alloc (2, 0);
7908     Store_field (cons, 1, rv);
7909     rv = cons;
7910     Store_field (cons, 0, pairv);
7911   }
7912
7913   CAMLreturn (rv);
7914 }
7915
7916 ";
7917
7918   (* Struct copy functions. *)
7919
7920   let emit_ocaml_copy_list_function typ =
7921     pr "static CAMLprim value\n";
7922     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7923     pr "{\n";
7924     pr "  CAMLparam0 ();\n";
7925     pr "  CAMLlocal2 (rv, v);\n";
7926     pr "  unsigned int i;\n";
7927     pr "\n";
7928     pr "  if (%ss->len == 0)\n" typ;
7929     pr "    CAMLreturn (Atom (0));\n";
7930     pr "  else {\n";
7931     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7932     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7933     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7934     pr "      caml_modify (&Field (rv, i), v);\n";
7935     pr "    }\n";
7936     pr "    CAMLreturn (rv);\n";
7937     pr "  }\n";
7938     pr "}\n";
7939     pr "\n";
7940   in
7941
7942   List.iter (
7943     fun (typ, cols) ->
7944       let has_optpercent_col =
7945         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7946
7947       pr "static CAMLprim value\n";
7948       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7949       pr "{\n";
7950       pr "  CAMLparam0 ();\n";
7951       if has_optpercent_col then
7952         pr "  CAMLlocal3 (rv, v, v2);\n"
7953       else
7954         pr "  CAMLlocal2 (rv, v);\n";
7955       pr "\n";
7956       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7957       iteri (
7958         fun i col ->
7959           (match col with
7960            | name, FString ->
7961                pr "  v = caml_copy_string (%s->%s);\n" typ name
7962            | name, FBuffer ->
7963                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7964                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7965                  typ name typ name
7966            | name, FUUID ->
7967                pr "  v = caml_alloc_string (32);\n";
7968                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7969            | name, (FBytes|FInt64|FUInt64) ->
7970                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7971            | name, (FInt32|FUInt32) ->
7972                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7973            | name, FOptPercent ->
7974                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7975                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7976                pr "    v = caml_alloc (1, 0);\n";
7977                pr "    Store_field (v, 0, v2);\n";
7978                pr "  } else /* None */\n";
7979                pr "    v = Val_int (0);\n";
7980            | name, FChar ->
7981                pr "  v = Val_int (%s->%s);\n" typ name
7982           );
7983           pr "  Store_field (rv, %d, v);\n" i
7984       ) cols;
7985       pr "  CAMLreturn (rv);\n";
7986       pr "}\n";
7987       pr "\n";
7988   ) structs;
7989
7990   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7991   List.iter (
7992     function
7993     | typ, (RStructListOnly | RStructAndList) ->
7994         (* generate the function for typ *)
7995         emit_ocaml_copy_list_function typ
7996     | typ, _ -> () (* empty *)
7997   ) (rstructs_used_by all_functions);
7998
7999   (* The wrappers. *)
8000   List.iter (
8001     fun (name, style, _, _, _, _, _) ->
8002       pr "/* Automatically generated wrapper for function\n";
8003       pr " * ";
8004       generate_ocaml_prototype name style;
8005       pr " */\n";
8006       pr "\n";
8007
8008       let params =
8009         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8010
8011       let needs_extra_vs =
8012         match fst style with RConstOptString _ -> true | _ -> false in
8013
8014       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8015       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8016       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8017       pr "\n";
8018
8019       pr "CAMLprim value\n";
8020       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8021       List.iter (pr ", value %s") (List.tl params);
8022       pr ")\n";
8023       pr "{\n";
8024
8025       (match params with
8026        | [p1; p2; p3; p4; p5] ->
8027            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8028        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8029            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8030            pr "  CAMLxparam%d (%s);\n"
8031              (List.length rest) (String.concat ", " rest)
8032        | ps ->
8033            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8034       );
8035       if not needs_extra_vs then
8036         pr "  CAMLlocal1 (rv);\n"
8037       else
8038         pr "  CAMLlocal3 (rv, v, v2);\n";
8039       pr "\n";
8040
8041       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8042       pr "  if (g == NULL)\n";
8043       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8044       pr "\n";
8045
8046       List.iter (
8047         function
8048         | Pathname n
8049         | Device n | Dev_or_Path n
8050         | String n
8051         | FileIn n
8052         | FileOut n ->
8053             pr "  const char *%s = String_val (%sv);\n" n n
8054         | OptString n ->
8055             pr "  const char *%s =\n" n;
8056             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8057               n n
8058         | StringList n | DeviceList n ->
8059             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8060         | Bool n ->
8061             pr "  int %s = Bool_val (%sv);\n" n n
8062         | Int n ->
8063             pr "  int %s = Int_val (%sv);\n" n n
8064         | Int64 n ->
8065             pr "  int64_t %s = Int64_val (%sv);\n" n n
8066       ) (snd style);
8067       let error_code =
8068         match fst style with
8069         | RErr -> pr "  int r;\n"; "-1"
8070         | RInt _ -> pr "  int r;\n"; "-1"
8071         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8072         | RBool _ -> pr "  int r;\n"; "-1"
8073         | RConstString _ | RConstOptString _ ->
8074             pr "  const char *r;\n"; "NULL"
8075         | RString _ -> pr "  char *r;\n"; "NULL"
8076         | RStringList _ ->
8077             pr "  int i;\n";
8078             pr "  char **r;\n";
8079             "NULL"
8080         | RStruct (_, typ) ->
8081             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8082         | RStructList (_, typ) ->
8083             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8084         | RHashtable _ ->
8085             pr "  int i;\n";
8086             pr "  char **r;\n";
8087             "NULL"
8088         | RBufferOut _ ->
8089             pr "  char *r;\n";
8090             pr "  size_t size;\n";
8091             "NULL" in
8092       pr "\n";
8093
8094       pr "  caml_enter_blocking_section ();\n";
8095       pr "  r = guestfs_%s " name;
8096       generate_c_call_args ~handle:"g" style;
8097       pr ";\n";
8098       pr "  caml_leave_blocking_section ();\n";
8099
8100       List.iter (
8101         function
8102         | StringList n | DeviceList n ->
8103             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8104         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8105         | Bool _ | Int _ | Int64 _
8106         | FileIn _ | FileOut _ -> ()
8107       ) (snd style);
8108
8109       pr "  if (r == %s)\n" error_code;
8110       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8111       pr "\n";
8112
8113       (match fst style with
8114        | RErr -> pr "  rv = Val_unit;\n"
8115        | RInt _ -> pr "  rv = Val_int (r);\n"
8116        | RInt64 _ ->
8117            pr "  rv = caml_copy_int64 (r);\n"
8118        | RBool _ -> pr "  rv = Val_bool (r);\n"
8119        | RConstString _ ->
8120            pr "  rv = caml_copy_string (r);\n"
8121        | RConstOptString _ ->
8122            pr "  if (r) { /* Some string */\n";
8123            pr "    v = caml_alloc (1, 0);\n";
8124            pr "    v2 = caml_copy_string (r);\n";
8125            pr "    Store_field (v, 0, v2);\n";
8126            pr "  } else /* None */\n";
8127            pr "    v = Val_int (0);\n";
8128        | RString _ ->
8129            pr "  rv = caml_copy_string (r);\n";
8130            pr "  free (r);\n"
8131        | RStringList _ ->
8132            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8133            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8134            pr "  free (r);\n"
8135        | RStruct (_, typ) ->
8136            pr "  rv = copy_%s (r);\n" typ;
8137            pr "  guestfs_free_%s (r);\n" typ;
8138        | RStructList (_, typ) ->
8139            pr "  rv = copy_%s_list (r);\n" typ;
8140            pr "  guestfs_free_%s_list (r);\n" typ;
8141        | RHashtable _ ->
8142            pr "  rv = copy_table (r);\n";
8143            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8144            pr "  free (r);\n";
8145        | RBufferOut _ ->
8146            pr "  rv = caml_alloc_string (size);\n";
8147            pr "  memcpy (String_val (rv), r, size);\n";
8148       );
8149
8150       pr "  CAMLreturn (rv);\n";
8151       pr "}\n";
8152       pr "\n";
8153
8154       if List.length params > 5 then (
8155         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8156         pr "CAMLprim value ";
8157         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8158         pr "CAMLprim value\n";
8159         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8160         pr "{\n";
8161         pr "  return ocaml_guestfs_%s (argv[0]" name;
8162         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8163         pr ");\n";
8164         pr "}\n";
8165         pr "\n"
8166       )
8167   ) all_functions_sorted
8168
8169 and generate_ocaml_structure_decls () =
8170   List.iter (
8171     fun (typ, cols) ->
8172       pr "type %s = {\n" typ;
8173       List.iter (
8174         function
8175         | name, FString -> pr "  %s : string;\n" name
8176         | name, FBuffer -> pr "  %s : string;\n" name
8177         | name, FUUID -> pr "  %s : string;\n" name
8178         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8179         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8180         | name, FChar -> pr "  %s : char;\n" name
8181         | name, FOptPercent -> pr "  %s : float option;\n" name
8182       ) cols;
8183       pr "}\n";
8184       pr "\n"
8185   ) structs
8186
8187 and generate_ocaml_prototype ?(is_external = false) name style =
8188   if is_external then pr "external " else pr "val ";
8189   pr "%s : t -> " name;
8190   List.iter (
8191     function
8192     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8193     | OptString _ -> pr "string option -> "
8194     | StringList _ | DeviceList _ -> pr "string array -> "
8195     | Bool _ -> pr "bool -> "
8196     | Int _ -> pr "int -> "
8197     | Int64 _ -> pr "int64 -> "
8198   ) (snd style);
8199   (match fst style with
8200    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8201    | RInt _ -> pr "int"
8202    | RInt64 _ -> pr "int64"
8203    | RBool _ -> pr "bool"
8204    | RConstString _ -> pr "string"
8205    | RConstOptString _ -> pr "string option"
8206    | RString _ | RBufferOut _ -> pr "string"
8207    | RStringList _ -> pr "string array"
8208    | RStruct (_, typ) -> pr "%s" typ
8209    | RStructList (_, typ) -> pr "%s array" typ
8210    | RHashtable _ -> pr "(string * string) list"
8211   );
8212   if is_external then (
8213     pr " = ";
8214     if List.length (snd style) + 1 > 5 then
8215       pr "\"ocaml_guestfs_%s_byte\" " name;
8216     pr "\"ocaml_guestfs_%s\"" name
8217   );
8218   pr "\n"
8219
8220 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8221 and generate_perl_xs () =
8222   generate_header CStyle LGPLv2plus;
8223
8224   pr "\
8225 #include \"EXTERN.h\"
8226 #include \"perl.h\"
8227 #include \"XSUB.h\"
8228
8229 #include <guestfs.h>
8230
8231 #ifndef PRId64
8232 #define PRId64 \"lld\"
8233 #endif
8234
8235 static SV *
8236 my_newSVll(long long val) {
8237 #ifdef USE_64_BIT_ALL
8238   return newSViv(val);
8239 #else
8240   char buf[100];
8241   int len;
8242   len = snprintf(buf, 100, \"%%\" PRId64, val);
8243   return newSVpv(buf, len);
8244 #endif
8245 }
8246
8247 #ifndef PRIu64
8248 #define PRIu64 \"llu\"
8249 #endif
8250
8251 static SV *
8252 my_newSVull(unsigned long long val) {
8253 #ifdef USE_64_BIT_ALL
8254   return newSVuv(val);
8255 #else
8256   char buf[100];
8257   int len;
8258   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8259   return newSVpv(buf, len);
8260 #endif
8261 }
8262
8263 /* http://www.perlmonks.org/?node_id=680842 */
8264 static char **
8265 XS_unpack_charPtrPtr (SV *arg) {
8266   char **ret;
8267   AV *av;
8268   I32 i;
8269
8270   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8271     croak (\"array reference expected\");
8272
8273   av = (AV *)SvRV (arg);
8274   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8275   if (!ret)
8276     croak (\"malloc failed\");
8277
8278   for (i = 0; i <= av_len (av); i++) {
8279     SV **elem = av_fetch (av, i, 0);
8280
8281     if (!elem || !*elem)
8282       croak (\"missing element in list\");
8283
8284     ret[i] = SvPV_nolen (*elem);
8285   }
8286
8287   ret[i] = NULL;
8288
8289   return ret;
8290 }
8291
8292 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8293
8294 PROTOTYPES: ENABLE
8295
8296 guestfs_h *
8297 _create ()
8298    CODE:
8299       RETVAL = guestfs_create ();
8300       if (!RETVAL)
8301         croak (\"could not create guestfs handle\");
8302       guestfs_set_error_handler (RETVAL, NULL, NULL);
8303  OUTPUT:
8304       RETVAL
8305
8306 void
8307 DESTROY (g)
8308       guestfs_h *g;
8309  PPCODE:
8310       guestfs_close (g);
8311
8312 ";
8313
8314   List.iter (
8315     fun (name, style, _, _, _, _, _) ->
8316       (match fst style with
8317        | RErr -> pr "void\n"
8318        | RInt _ -> pr "SV *\n"
8319        | RInt64 _ -> pr "SV *\n"
8320        | RBool _ -> pr "SV *\n"
8321        | RConstString _ -> pr "SV *\n"
8322        | RConstOptString _ -> pr "SV *\n"
8323        | RString _ -> pr "SV *\n"
8324        | RBufferOut _ -> pr "SV *\n"
8325        | RStringList _
8326        | RStruct _ | RStructList _
8327        | RHashtable _ ->
8328            pr "void\n" (* all lists returned implictly on the stack *)
8329       );
8330       (* Call and arguments. *)
8331       pr "%s " name;
8332       generate_c_call_args ~handle:"g" ~decl:true style;
8333       pr "\n";
8334       pr "      guestfs_h *g;\n";
8335       iteri (
8336         fun i ->
8337           function
8338           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8339               pr "      char *%s;\n" n
8340           | OptString n ->
8341               (* http://www.perlmonks.org/?node_id=554277
8342                * Note that the implicit handle argument means we have
8343                * to add 1 to the ST(x) operator.
8344                *)
8345               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8346           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8347           | Bool n -> pr "      int %s;\n" n
8348           | Int n -> pr "      int %s;\n" n
8349           | Int64 n -> pr "      int64_t %s;\n" n
8350       ) (snd style);
8351
8352       let do_cleanups () =
8353         List.iter (
8354           function
8355           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8356           | Bool _ | Int _ | Int64 _
8357           | FileIn _ | FileOut _ -> ()
8358           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8359         ) (snd style)
8360       in
8361
8362       (* Code. *)
8363       (match fst style with
8364        | RErr ->
8365            pr "PREINIT:\n";
8366            pr "      int r;\n";
8367            pr " PPCODE:\n";
8368            pr "      r = guestfs_%s " name;
8369            generate_c_call_args ~handle:"g" style;
8370            pr ";\n";
8371            do_cleanups ();
8372            pr "      if (r == -1)\n";
8373            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8374        | RInt n
8375        | RBool n ->
8376            pr "PREINIT:\n";
8377            pr "      int %s;\n" n;
8378            pr "   CODE:\n";
8379            pr "      %s = guestfs_%s " n name;
8380            generate_c_call_args ~handle:"g" style;
8381            pr ";\n";
8382            do_cleanups ();
8383            pr "      if (%s == -1)\n" n;
8384            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8385            pr "      RETVAL = newSViv (%s);\n" n;
8386            pr " OUTPUT:\n";
8387            pr "      RETVAL\n"
8388        | RInt64 n ->
8389            pr "PREINIT:\n";
8390            pr "      int64_t %s;\n" n;
8391            pr "   CODE:\n";
8392            pr "      %s = guestfs_%s " n name;
8393            generate_c_call_args ~handle:"g" style;
8394            pr ";\n";
8395            do_cleanups ();
8396            pr "      if (%s == -1)\n" n;
8397            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8398            pr "      RETVAL = my_newSVll (%s);\n" n;
8399            pr " OUTPUT:\n";
8400            pr "      RETVAL\n"
8401        | RConstString n ->
8402            pr "PREINIT:\n";
8403            pr "      const char *%s;\n" n;
8404            pr "   CODE:\n";
8405            pr "      %s = guestfs_%s " n name;
8406            generate_c_call_args ~handle:"g" style;
8407            pr ";\n";
8408            do_cleanups ();
8409            pr "      if (%s == NULL)\n" n;
8410            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8411            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8412            pr " OUTPUT:\n";
8413            pr "      RETVAL\n"
8414        | RConstOptString n ->
8415            pr "PREINIT:\n";
8416            pr "      const char *%s;\n" n;
8417            pr "   CODE:\n";
8418            pr "      %s = guestfs_%s " n name;
8419            generate_c_call_args ~handle:"g" style;
8420            pr ";\n";
8421            do_cleanups ();
8422            pr "      if (%s == NULL)\n" n;
8423            pr "        RETVAL = &PL_sv_undef;\n";
8424            pr "      else\n";
8425            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8426            pr " OUTPUT:\n";
8427            pr "      RETVAL\n"
8428        | RString n ->
8429            pr "PREINIT:\n";
8430            pr "      char *%s;\n" n;
8431            pr "   CODE:\n";
8432            pr "      %s = guestfs_%s " n name;
8433            generate_c_call_args ~handle:"g" style;
8434            pr ";\n";
8435            do_cleanups ();
8436            pr "      if (%s == NULL)\n" n;
8437            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8438            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8439            pr "      free (%s);\n" n;
8440            pr " OUTPUT:\n";
8441            pr "      RETVAL\n"
8442        | RStringList n | RHashtable n ->
8443            pr "PREINIT:\n";
8444            pr "      char **%s;\n" n;
8445            pr "      int i, n;\n";
8446            pr " PPCODE:\n";
8447            pr "      %s = guestfs_%s " n name;
8448            generate_c_call_args ~handle:"g" style;
8449            pr ";\n";
8450            do_cleanups ();
8451            pr "      if (%s == NULL)\n" n;
8452            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8453            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8454            pr "      EXTEND (SP, n);\n";
8455            pr "      for (i = 0; i < n; ++i) {\n";
8456            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8457            pr "        free (%s[i]);\n" n;
8458            pr "      }\n";
8459            pr "      free (%s);\n" n;
8460        | RStruct (n, typ) ->
8461            let cols = cols_of_struct typ in
8462            generate_perl_struct_code typ cols name style n do_cleanups
8463        | RStructList (n, typ) ->
8464            let cols = cols_of_struct typ in
8465            generate_perl_struct_list_code typ cols name style n do_cleanups
8466        | RBufferOut n ->
8467            pr "PREINIT:\n";
8468            pr "      char *%s;\n" n;
8469            pr "      size_t size;\n";
8470            pr "   CODE:\n";
8471            pr "      %s = guestfs_%s " n name;
8472            generate_c_call_args ~handle:"g" style;
8473            pr ";\n";
8474            do_cleanups ();
8475            pr "      if (%s == NULL)\n" n;
8476            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8477            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8478            pr "      free (%s);\n" n;
8479            pr " OUTPUT:\n";
8480            pr "      RETVAL\n"
8481       );
8482
8483       pr "\n"
8484   ) all_functions
8485
8486 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8487   pr "PREINIT:\n";
8488   pr "      struct guestfs_%s_list *%s;\n" typ n;
8489   pr "      int i;\n";
8490   pr "      HV *hv;\n";
8491   pr " PPCODE:\n";
8492   pr "      %s = guestfs_%s " n name;
8493   generate_c_call_args ~handle:"g" style;
8494   pr ";\n";
8495   do_cleanups ();
8496   pr "      if (%s == NULL)\n" n;
8497   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8498   pr "      EXTEND (SP, %s->len);\n" n;
8499   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8500   pr "        hv = newHV ();\n";
8501   List.iter (
8502     function
8503     | name, FString ->
8504         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8505           name (String.length name) n name
8506     | name, FUUID ->
8507         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8508           name (String.length name) n name
8509     | name, FBuffer ->
8510         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8511           name (String.length name) n name n name
8512     | name, (FBytes|FUInt64) ->
8513         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8514           name (String.length name) n name
8515     | name, FInt64 ->
8516         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8517           name (String.length name) n name
8518     | name, (FInt32|FUInt32) ->
8519         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8520           name (String.length name) n name
8521     | name, FChar ->
8522         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8523           name (String.length name) n name
8524     | name, FOptPercent ->
8525         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8526           name (String.length name) n name
8527   ) cols;
8528   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8529   pr "      }\n";
8530   pr "      guestfs_free_%s_list (%s);\n" typ n
8531
8532 and generate_perl_struct_code typ cols name style n do_cleanups =
8533   pr "PREINIT:\n";
8534   pr "      struct guestfs_%s *%s;\n" typ n;
8535   pr " PPCODE:\n";
8536   pr "      %s = guestfs_%s " n name;
8537   generate_c_call_args ~handle:"g" style;
8538   pr ";\n";
8539   do_cleanups ();
8540   pr "      if (%s == NULL)\n" n;
8541   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8542   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8543   List.iter (
8544     fun ((name, _) as col) ->
8545       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8546
8547       match col with
8548       | name, FString ->
8549           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8550             n name
8551       | name, FBuffer ->
8552           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8553             n name n name
8554       | name, FUUID ->
8555           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8556             n name
8557       | name, (FBytes|FUInt64) ->
8558           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8559             n name
8560       | name, FInt64 ->
8561           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8562             n name
8563       | name, (FInt32|FUInt32) ->
8564           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8565             n name
8566       | name, FChar ->
8567           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8568             n name
8569       | name, FOptPercent ->
8570           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8571             n name
8572   ) cols;
8573   pr "      free (%s);\n" n
8574
8575 (* Generate Sys/Guestfs.pm. *)
8576 and generate_perl_pm () =
8577   generate_header HashStyle LGPLv2plus;
8578
8579   pr "\
8580 =pod
8581
8582 =head1 NAME
8583
8584 Sys::Guestfs - Perl bindings for libguestfs
8585
8586 =head1 SYNOPSIS
8587
8588  use Sys::Guestfs;
8589
8590  my $h = Sys::Guestfs->new ();
8591  $h->add_drive ('guest.img');
8592  $h->launch ();
8593  $h->mount ('/dev/sda1', '/');
8594  $h->touch ('/hello');
8595  $h->sync ();
8596
8597 =head1 DESCRIPTION
8598
8599 The C<Sys::Guestfs> module provides a Perl XS binding to the
8600 libguestfs API for examining and modifying virtual machine
8601 disk images.
8602
8603 Amongst the things this is good for: making batch configuration
8604 changes to guests, getting disk used/free statistics (see also:
8605 virt-df), migrating between virtualization systems (see also:
8606 virt-p2v), performing partial backups, performing partial guest
8607 clones, cloning guests and changing registry/UUID/hostname info, and
8608 much else besides.
8609
8610 Libguestfs uses Linux kernel and qemu code, and can access any type of
8611 guest filesystem that Linux and qemu can, including but not limited
8612 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8613 schemes, qcow, qcow2, vmdk.
8614
8615 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8616 LVs, what filesystem is in each LV, etc.).  It can also run commands
8617 in the context of the guest.  Also you can access filesystems over
8618 FUSE.
8619
8620 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8621 functions for using libguestfs from Perl, including integration
8622 with libvirt.
8623
8624 =head1 ERRORS
8625
8626 All errors turn into calls to C<croak> (see L<Carp(3)>).
8627
8628 =head1 METHODS
8629
8630 =over 4
8631
8632 =cut
8633
8634 package Sys::Guestfs;
8635
8636 use strict;
8637 use warnings;
8638
8639 require XSLoader;
8640 XSLoader::load ('Sys::Guestfs');
8641
8642 =item $h = Sys::Guestfs->new ();
8643
8644 Create a new guestfs handle.
8645
8646 =cut
8647
8648 sub new {
8649   my $proto = shift;
8650   my $class = ref ($proto) || $proto;
8651
8652   my $self = Sys::Guestfs::_create ();
8653   bless $self, $class;
8654   return $self;
8655 }
8656
8657 ";
8658
8659   (* Actions.  We only need to print documentation for these as
8660    * they are pulled in from the XS code automatically.
8661    *)
8662   List.iter (
8663     fun (name, style, _, flags, _, _, longdesc) ->
8664       if not (List.mem NotInDocs flags) then (
8665         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8666         pr "=item ";
8667         generate_perl_prototype name style;
8668         pr "\n\n";
8669         pr "%s\n\n" longdesc;
8670         if List.mem ProtocolLimitWarning flags then
8671           pr "%s\n\n" protocol_limit_warning;
8672         if List.mem DangerWillRobinson flags then
8673           pr "%s\n\n" danger_will_robinson;
8674         match deprecation_notice flags with
8675         | None -> ()
8676         | Some txt -> pr "%s\n\n" txt
8677       )
8678   ) all_functions_sorted;
8679
8680   (* End of file. *)
8681   pr "\
8682 =cut
8683
8684 1;
8685
8686 =back
8687
8688 =head1 COPYRIGHT
8689
8690 Copyright (C) %s Red Hat Inc.
8691
8692 =head1 LICENSE
8693
8694 Please see the file COPYING.LIB for the full license.
8695
8696 =head1 SEE ALSO
8697
8698 L<guestfs(3)>,
8699 L<guestfish(1)>,
8700 L<http://libguestfs.org>,
8701 L<Sys::Guestfs::Lib(3)>.
8702
8703 =cut
8704 " copyright_years
8705
8706 and generate_perl_prototype name style =
8707   (match fst style with
8708    | RErr -> ()
8709    | RBool n
8710    | RInt n
8711    | RInt64 n
8712    | RConstString n
8713    | RConstOptString n
8714    | RString n
8715    | RBufferOut n -> pr "$%s = " n
8716    | RStruct (n,_)
8717    | RHashtable n -> pr "%%%s = " n
8718    | RStringList n
8719    | RStructList (n,_) -> pr "@%s = " n
8720   );
8721   pr "$h->%s (" name;
8722   let comma = ref false in
8723   List.iter (
8724     fun arg ->
8725       if !comma then pr ", ";
8726       comma := true;
8727       match arg with
8728       | Pathname n | Device n | Dev_or_Path n | String n
8729       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8730           pr "$%s" n
8731       | StringList n | DeviceList n ->
8732           pr "\\@%s" n
8733   ) (snd style);
8734   pr ");"
8735
8736 (* Generate Python C module. *)
8737 and generate_python_c () =
8738   generate_header CStyle LGPLv2plus;
8739
8740   pr "\
8741 #include <Python.h>
8742
8743 #include <stdio.h>
8744 #include <stdlib.h>
8745 #include <assert.h>
8746
8747 #include \"guestfs.h\"
8748
8749 typedef struct {
8750   PyObject_HEAD
8751   guestfs_h *g;
8752 } Pyguestfs_Object;
8753
8754 static guestfs_h *
8755 get_handle (PyObject *obj)
8756 {
8757   assert (obj);
8758   assert (obj != Py_None);
8759   return ((Pyguestfs_Object *) obj)->g;
8760 }
8761
8762 static PyObject *
8763 put_handle (guestfs_h *g)
8764 {
8765   assert (g);
8766   return
8767     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8768 }
8769
8770 /* This list should be freed (but not the strings) after use. */
8771 static char **
8772 get_string_list (PyObject *obj)
8773 {
8774   int i, len;
8775   char **r;
8776
8777   assert (obj);
8778
8779   if (!PyList_Check (obj)) {
8780     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8781     return NULL;
8782   }
8783
8784   len = PyList_Size (obj);
8785   r = malloc (sizeof (char *) * (len+1));
8786   if (r == NULL) {
8787     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8788     return NULL;
8789   }
8790
8791   for (i = 0; i < len; ++i)
8792     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8793   r[len] = NULL;
8794
8795   return r;
8796 }
8797
8798 static PyObject *
8799 put_string_list (char * const * const argv)
8800 {
8801   PyObject *list;
8802   int argc, i;
8803
8804   for (argc = 0; argv[argc] != NULL; ++argc)
8805     ;
8806
8807   list = PyList_New (argc);
8808   for (i = 0; i < argc; ++i)
8809     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8810
8811   return list;
8812 }
8813
8814 static PyObject *
8815 put_table (char * const * const argv)
8816 {
8817   PyObject *list, *item;
8818   int argc, i;
8819
8820   for (argc = 0; argv[argc] != NULL; ++argc)
8821     ;
8822
8823   list = PyList_New (argc >> 1);
8824   for (i = 0; i < argc; i += 2) {
8825     item = PyTuple_New (2);
8826     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8827     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8828     PyList_SetItem (list, i >> 1, item);
8829   }
8830
8831   return list;
8832 }
8833
8834 static void
8835 free_strings (char **argv)
8836 {
8837   int argc;
8838
8839   for (argc = 0; argv[argc] != NULL; ++argc)
8840     free (argv[argc]);
8841   free (argv);
8842 }
8843
8844 static PyObject *
8845 py_guestfs_create (PyObject *self, PyObject *args)
8846 {
8847   guestfs_h *g;
8848
8849   g = guestfs_create ();
8850   if (g == NULL) {
8851     PyErr_SetString (PyExc_RuntimeError,
8852                      \"guestfs.create: failed to allocate handle\");
8853     return NULL;
8854   }
8855   guestfs_set_error_handler (g, NULL, NULL);
8856   return put_handle (g);
8857 }
8858
8859 static PyObject *
8860 py_guestfs_close (PyObject *self, PyObject *args)
8861 {
8862   PyObject *py_g;
8863   guestfs_h *g;
8864
8865   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8866     return NULL;
8867   g = get_handle (py_g);
8868
8869   guestfs_close (g);
8870
8871   Py_INCREF (Py_None);
8872   return Py_None;
8873 }
8874
8875 ";
8876
8877   let emit_put_list_function typ =
8878     pr "static PyObject *\n";
8879     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8880     pr "{\n";
8881     pr "  PyObject *list;\n";
8882     pr "  int i;\n";
8883     pr "\n";
8884     pr "  list = PyList_New (%ss->len);\n" typ;
8885     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8886     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8887     pr "  return list;\n";
8888     pr "};\n";
8889     pr "\n"
8890   in
8891
8892   (* Structures, turned into Python dictionaries. *)
8893   List.iter (
8894     fun (typ, cols) ->
8895       pr "static PyObject *\n";
8896       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8897       pr "{\n";
8898       pr "  PyObject *dict;\n";
8899       pr "\n";
8900       pr "  dict = PyDict_New ();\n";
8901       List.iter (
8902         function
8903         | name, FString ->
8904             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8905             pr "                        PyString_FromString (%s->%s));\n"
8906               typ name
8907         | name, FBuffer ->
8908             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8909             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8910               typ name typ name
8911         | name, FUUID ->
8912             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8913             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8914               typ name
8915         | name, (FBytes|FUInt64) ->
8916             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8917             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8918               typ name
8919         | name, FInt64 ->
8920             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8921             pr "                        PyLong_FromLongLong (%s->%s));\n"
8922               typ name
8923         | name, FUInt32 ->
8924             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8925             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8926               typ name
8927         | name, FInt32 ->
8928             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8929             pr "                        PyLong_FromLong (%s->%s));\n"
8930               typ name
8931         | name, FOptPercent ->
8932             pr "  if (%s->%s >= 0)\n" typ name;
8933             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8934             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8935               typ name;
8936             pr "  else {\n";
8937             pr "    Py_INCREF (Py_None);\n";
8938             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8939             pr "  }\n"
8940         | name, FChar ->
8941             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8942             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8943       ) cols;
8944       pr "  return dict;\n";
8945       pr "};\n";
8946       pr "\n";
8947
8948   ) structs;
8949
8950   (* Emit a put_TYPE_list function definition only if that function is used. *)
8951   List.iter (
8952     function
8953     | typ, (RStructListOnly | RStructAndList) ->
8954         (* generate the function for typ *)
8955         emit_put_list_function typ
8956     | typ, _ -> () (* empty *)
8957   ) (rstructs_used_by all_functions);
8958
8959   (* Python wrapper functions. *)
8960   List.iter (
8961     fun (name, style, _, _, _, _, _) ->
8962       pr "static PyObject *\n";
8963       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8964       pr "{\n";
8965
8966       pr "  PyObject *py_g;\n";
8967       pr "  guestfs_h *g;\n";
8968       pr "  PyObject *py_r;\n";
8969
8970       let error_code =
8971         match fst style with
8972         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8973         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8974         | RConstString _ | RConstOptString _ ->
8975             pr "  const char *r;\n"; "NULL"
8976         | RString _ -> pr "  char *r;\n"; "NULL"
8977         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8978         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8979         | RStructList (_, typ) ->
8980             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8981         | RBufferOut _ ->
8982             pr "  char *r;\n";
8983             pr "  size_t size;\n";
8984             "NULL" in
8985
8986       List.iter (
8987         function
8988         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8989             pr "  const char *%s;\n" n
8990         | OptString n -> pr "  const char *%s;\n" n
8991         | StringList n | DeviceList n ->
8992             pr "  PyObject *py_%s;\n" n;
8993             pr "  char **%s;\n" n
8994         | Bool n -> pr "  int %s;\n" n
8995         | Int n -> pr "  int %s;\n" n
8996         | Int64 n -> pr "  long long %s;\n" n
8997       ) (snd style);
8998
8999       pr "\n";
9000
9001       (* Convert the parameters. *)
9002       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9003       List.iter (
9004         function
9005         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9006         | OptString _ -> pr "z"
9007         | StringList _ | DeviceList _ -> pr "O"
9008         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9009         | Int _ -> pr "i"
9010         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9011                              * emulate C's int/long/long long in Python?
9012                              *)
9013       ) (snd style);
9014       pr ":guestfs_%s\",\n" name;
9015       pr "                         &py_g";
9016       List.iter (
9017         function
9018         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9019         | OptString n -> pr ", &%s" n
9020         | StringList n | DeviceList n -> pr ", &py_%s" n
9021         | Bool n -> pr ", &%s" n
9022         | Int n -> pr ", &%s" n
9023         | Int64 n -> pr ", &%s" n
9024       ) (snd style);
9025
9026       pr "))\n";
9027       pr "    return NULL;\n";
9028
9029       pr "  g = get_handle (py_g);\n";
9030       List.iter (
9031         function
9032         | Pathname _ | Device _ | Dev_or_Path _ | String _
9033         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9034         | StringList n | DeviceList n ->
9035             pr "  %s = get_string_list (py_%s);\n" n n;
9036             pr "  if (!%s) return NULL;\n" n
9037       ) (snd style);
9038
9039       pr "\n";
9040
9041       pr "  r = guestfs_%s " name;
9042       generate_c_call_args ~handle:"g" style;
9043       pr ";\n";
9044
9045       List.iter (
9046         function
9047         | Pathname _ | Device _ | Dev_or_Path _ | String _
9048         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9049         | StringList n | DeviceList n ->
9050             pr "  free (%s);\n" n
9051       ) (snd style);
9052
9053       pr "  if (r == %s) {\n" error_code;
9054       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9055       pr "    return NULL;\n";
9056       pr "  }\n";
9057       pr "\n";
9058
9059       (match fst style with
9060        | RErr ->
9061            pr "  Py_INCREF (Py_None);\n";
9062            pr "  py_r = Py_None;\n"
9063        | RInt _
9064        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9065        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9066        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9067        | RConstOptString _ ->
9068            pr "  if (r)\n";
9069            pr "    py_r = PyString_FromString (r);\n";
9070            pr "  else {\n";
9071            pr "    Py_INCREF (Py_None);\n";
9072            pr "    py_r = Py_None;\n";
9073            pr "  }\n"
9074        | RString _ ->
9075            pr "  py_r = PyString_FromString (r);\n";
9076            pr "  free (r);\n"
9077        | RStringList _ ->
9078            pr "  py_r = put_string_list (r);\n";
9079            pr "  free_strings (r);\n"
9080        | RStruct (_, typ) ->
9081            pr "  py_r = put_%s (r);\n" typ;
9082            pr "  guestfs_free_%s (r);\n" typ
9083        | RStructList (_, typ) ->
9084            pr "  py_r = put_%s_list (r);\n" typ;
9085            pr "  guestfs_free_%s_list (r);\n" typ
9086        | RHashtable n ->
9087            pr "  py_r = put_table (r);\n";
9088            pr "  free_strings (r);\n"
9089        | RBufferOut _ ->
9090            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9091            pr "  free (r);\n"
9092       );
9093
9094       pr "  return py_r;\n";
9095       pr "}\n";
9096       pr "\n"
9097   ) all_functions;
9098
9099   (* Table of functions. *)
9100   pr "static PyMethodDef methods[] = {\n";
9101   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9102   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9103   List.iter (
9104     fun (name, _, _, _, _, _, _) ->
9105       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9106         name name
9107   ) all_functions;
9108   pr "  { NULL, NULL, 0, NULL }\n";
9109   pr "};\n";
9110   pr "\n";
9111
9112   (* Init function. *)
9113   pr "\
9114 void
9115 initlibguestfsmod (void)
9116 {
9117   static int initialized = 0;
9118
9119   if (initialized) return;
9120   Py_InitModule ((char *) \"libguestfsmod\", methods);
9121   initialized = 1;
9122 }
9123 "
9124
9125 (* Generate Python module. *)
9126 and generate_python_py () =
9127   generate_header HashStyle LGPLv2plus;
9128
9129   pr "\
9130 u\"\"\"Python bindings for libguestfs
9131
9132 import guestfs
9133 g = guestfs.GuestFS ()
9134 g.add_drive (\"guest.img\")
9135 g.launch ()
9136 parts = g.list_partitions ()
9137
9138 The guestfs module provides a Python binding to the libguestfs API
9139 for examining and modifying virtual machine disk images.
9140
9141 Amongst the things this is good for: making batch configuration
9142 changes to guests, getting disk used/free statistics (see also:
9143 virt-df), migrating between virtualization systems (see also:
9144 virt-p2v), performing partial backups, performing partial guest
9145 clones, cloning guests and changing registry/UUID/hostname info, and
9146 much else besides.
9147
9148 Libguestfs uses Linux kernel and qemu code, and can access any type of
9149 guest filesystem that Linux and qemu can, including but not limited
9150 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9151 schemes, qcow, qcow2, vmdk.
9152
9153 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9154 LVs, what filesystem is in each LV, etc.).  It can also run commands
9155 in the context of the guest.  Also you can access filesystems over
9156 FUSE.
9157
9158 Errors which happen while using the API are turned into Python
9159 RuntimeError exceptions.
9160
9161 To create a guestfs handle you usually have to perform the following
9162 sequence of calls:
9163
9164 # Create the handle, call add_drive at least once, and possibly
9165 # several times if the guest has multiple block devices:
9166 g = guestfs.GuestFS ()
9167 g.add_drive (\"guest.img\")
9168
9169 # Launch the qemu subprocess and wait for it to become ready:
9170 g.launch ()
9171
9172 # Now you can issue commands, for example:
9173 logvols = g.lvs ()
9174
9175 \"\"\"
9176
9177 import libguestfsmod
9178
9179 class GuestFS:
9180     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9181
9182     def __init__ (self):
9183         \"\"\"Create a new libguestfs handle.\"\"\"
9184         self._o = libguestfsmod.create ()
9185
9186     def __del__ (self):
9187         libguestfsmod.close (self._o)
9188
9189 ";
9190
9191   List.iter (
9192     fun (name, style, _, flags, _, _, longdesc) ->
9193       pr "    def %s " name;
9194       generate_py_call_args ~handle:"self" (snd style);
9195       pr ":\n";
9196
9197       if not (List.mem NotInDocs flags) then (
9198         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9199         let doc =
9200           match fst style with
9201           | RErr | RInt _ | RInt64 _ | RBool _
9202           | RConstOptString _ | RConstString _
9203           | RString _ | RBufferOut _ -> doc
9204           | RStringList _ ->
9205               doc ^ "\n\nThis function returns a list of strings."
9206           | RStruct (_, typ) ->
9207               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9208           | RStructList (_, typ) ->
9209               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9210           | RHashtable _ ->
9211               doc ^ "\n\nThis function returns a dictionary." in
9212         let doc =
9213           if List.mem ProtocolLimitWarning flags then
9214             doc ^ "\n\n" ^ protocol_limit_warning
9215           else doc in
9216         let doc =
9217           if List.mem DangerWillRobinson flags then
9218             doc ^ "\n\n" ^ danger_will_robinson
9219           else doc in
9220         let doc =
9221           match deprecation_notice flags with
9222           | None -> doc
9223           | Some txt -> doc ^ "\n\n" ^ txt in
9224         let doc = pod2text ~width:60 name doc in
9225         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9226         let doc = String.concat "\n        " doc in
9227         pr "        u\"\"\"%s\"\"\"\n" doc;
9228       );
9229       pr "        return libguestfsmod.%s " name;
9230       generate_py_call_args ~handle:"self._o" (snd style);
9231       pr "\n";
9232       pr "\n";
9233   ) all_functions
9234
9235 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9236 and generate_py_call_args ~handle args =
9237   pr "(%s" handle;
9238   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9239   pr ")"
9240
9241 (* Useful if you need the longdesc POD text as plain text.  Returns a
9242  * list of lines.
9243  *
9244  * Because this is very slow (the slowest part of autogeneration),
9245  * we memoize the results.
9246  *)
9247 and pod2text ~width name longdesc =
9248   let key = width, name, longdesc in
9249   try Hashtbl.find pod2text_memo key
9250   with Not_found ->
9251     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9252     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9253     close_out chan;
9254     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9255     let chan = open_process_in cmd in
9256     let lines = ref [] in
9257     let rec loop i =
9258       let line = input_line chan in
9259       if i = 1 then             (* discard the first line of output *)
9260         loop (i+1)
9261       else (
9262         let line = triml line in
9263         lines := line :: !lines;
9264         loop (i+1)
9265       ) in
9266     let lines = try loop 1 with End_of_file -> List.rev !lines in
9267     unlink filename;
9268     (match close_process_in chan with
9269      | WEXITED 0 -> ()
9270      | WEXITED i ->
9271          failwithf "pod2text: process exited with non-zero status (%d)" i
9272      | WSIGNALED i | WSTOPPED i ->
9273          failwithf "pod2text: process signalled or stopped by signal %d" i
9274     );
9275     Hashtbl.add pod2text_memo key lines;
9276     pod2text_memo_updated ();
9277     lines
9278
9279 (* Generate ruby bindings. *)
9280 and generate_ruby_c () =
9281   generate_header CStyle LGPLv2plus;
9282
9283   pr "\
9284 #include <stdio.h>
9285 #include <stdlib.h>
9286
9287 #include <ruby.h>
9288
9289 #include \"guestfs.h\"
9290
9291 #include \"extconf.h\"
9292
9293 /* For Ruby < 1.9 */
9294 #ifndef RARRAY_LEN
9295 #define RARRAY_LEN(r) (RARRAY((r))->len)
9296 #endif
9297
9298 static VALUE m_guestfs;                 /* guestfs module */
9299 static VALUE c_guestfs;                 /* guestfs_h handle */
9300 static VALUE e_Error;                   /* used for all errors */
9301
9302 static void ruby_guestfs_free (void *p)
9303 {
9304   if (!p) return;
9305   guestfs_close ((guestfs_h *) p);
9306 }
9307
9308 static VALUE ruby_guestfs_create (VALUE m)
9309 {
9310   guestfs_h *g;
9311
9312   g = guestfs_create ();
9313   if (!g)
9314     rb_raise (e_Error, \"failed to create guestfs handle\");
9315
9316   /* Don't print error messages to stderr by default. */
9317   guestfs_set_error_handler (g, NULL, NULL);
9318
9319   /* Wrap it, and make sure the close function is called when the
9320    * handle goes away.
9321    */
9322   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9323 }
9324
9325 static VALUE ruby_guestfs_close (VALUE gv)
9326 {
9327   guestfs_h *g;
9328   Data_Get_Struct (gv, guestfs_h, g);
9329
9330   ruby_guestfs_free (g);
9331   DATA_PTR (gv) = NULL;
9332
9333   return Qnil;
9334 }
9335
9336 ";
9337
9338   List.iter (
9339     fun (name, style, _, _, _, _, _) ->
9340       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9341       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9342       pr ")\n";
9343       pr "{\n";
9344       pr "  guestfs_h *g;\n";
9345       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9346       pr "  if (!g)\n";
9347       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9348         name;
9349       pr "\n";
9350
9351       List.iter (
9352         function
9353         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9354             pr "  Check_Type (%sv, T_STRING);\n" n;
9355             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9356             pr "  if (!%s)\n" n;
9357             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9358             pr "              \"%s\", \"%s\");\n" n name
9359         | OptString n ->
9360             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9361         | StringList n | DeviceList n ->
9362             pr "  char **%s;\n" n;
9363             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9364             pr "  {\n";
9365             pr "    int i, len;\n";
9366             pr "    len = RARRAY_LEN (%sv);\n" n;
9367             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9368               n;
9369             pr "    for (i = 0; i < len; ++i) {\n";
9370             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9371             pr "      %s[i] = StringValueCStr (v);\n" n;
9372             pr "    }\n";
9373             pr "    %s[len] = NULL;\n" n;
9374             pr "  }\n";
9375         | Bool n ->
9376             pr "  int %s = RTEST (%sv);\n" n n
9377         | Int n ->
9378             pr "  int %s = NUM2INT (%sv);\n" n n
9379         | Int64 n ->
9380             pr "  long long %s = NUM2LL (%sv);\n" n n
9381       ) (snd style);
9382       pr "\n";
9383
9384       let error_code =
9385         match fst style with
9386         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9387         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9388         | RConstString _ | RConstOptString _ ->
9389             pr "  const char *r;\n"; "NULL"
9390         | RString _ -> pr "  char *r;\n"; "NULL"
9391         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9392         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9393         | RStructList (_, typ) ->
9394             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9395         | RBufferOut _ ->
9396             pr "  char *r;\n";
9397             pr "  size_t size;\n";
9398             "NULL" in
9399       pr "\n";
9400
9401       pr "  r = guestfs_%s " name;
9402       generate_c_call_args ~handle:"g" style;
9403       pr ";\n";
9404
9405       List.iter (
9406         function
9407         | Pathname _ | Device _ | Dev_or_Path _ | String _
9408         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9409         | StringList n | DeviceList n ->
9410             pr "  free (%s);\n" n
9411       ) (snd style);
9412
9413       pr "  if (r == %s)\n" error_code;
9414       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9415       pr "\n";
9416
9417       (match fst style with
9418        | RErr ->
9419            pr "  return Qnil;\n"
9420        | RInt _ | RBool _ ->
9421            pr "  return INT2NUM (r);\n"
9422        | RInt64 _ ->
9423            pr "  return ULL2NUM (r);\n"
9424        | RConstString _ ->
9425            pr "  return rb_str_new2 (r);\n";
9426        | RConstOptString _ ->
9427            pr "  if (r)\n";
9428            pr "    return rb_str_new2 (r);\n";
9429            pr "  else\n";
9430            pr "    return Qnil;\n";
9431        | RString _ ->
9432            pr "  VALUE rv = rb_str_new2 (r);\n";
9433            pr "  free (r);\n";
9434            pr "  return rv;\n";
9435        | RStringList _ ->
9436            pr "  int i, len = 0;\n";
9437            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9438            pr "  VALUE rv = rb_ary_new2 (len);\n";
9439            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9440            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9441            pr "    free (r[i]);\n";
9442            pr "  }\n";
9443            pr "  free (r);\n";
9444            pr "  return rv;\n"
9445        | RStruct (_, typ) ->
9446            let cols = cols_of_struct typ in
9447            generate_ruby_struct_code typ cols
9448        | RStructList (_, typ) ->
9449            let cols = cols_of_struct typ in
9450            generate_ruby_struct_list_code typ cols
9451        | RHashtable _ ->
9452            pr "  VALUE rv = rb_hash_new ();\n";
9453            pr "  int i;\n";
9454            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9455            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9456            pr "    free (r[i]);\n";
9457            pr "    free (r[i+1]);\n";
9458            pr "  }\n";
9459            pr "  free (r);\n";
9460            pr "  return rv;\n"
9461        | RBufferOut _ ->
9462            pr "  VALUE rv = rb_str_new (r, size);\n";
9463            pr "  free (r);\n";
9464            pr "  return rv;\n";
9465       );
9466
9467       pr "}\n";
9468       pr "\n"
9469   ) all_functions;
9470
9471   pr "\
9472 /* Initialize the module. */
9473 void Init__guestfs ()
9474 {
9475   m_guestfs = rb_define_module (\"Guestfs\");
9476   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9477   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9478
9479   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9480   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9481
9482 ";
9483   (* Define the rest of the methods. *)
9484   List.iter (
9485     fun (name, style, _, _, _, _, _) ->
9486       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9487       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9488   ) all_functions;
9489
9490   pr "}\n"
9491
9492 (* Ruby code to return a struct. *)
9493 and generate_ruby_struct_code typ cols =
9494   pr "  VALUE rv = rb_hash_new ();\n";
9495   List.iter (
9496     function
9497     | name, FString ->
9498         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9499     | name, FBuffer ->
9500         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9501     | name, FUUID ->
9502         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9503     | name, (FBytes|FUInt64) ->
9504         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9505     | name, FInt64 ->
9506         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9507     | name, FUInt32 ->
9508         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9509     | name, FInt32 ->
9510         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9511     | name, FOptPercent ->
9512         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9513     | name, FChar -> (* XXX wrong? *)
9514         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9515   ) cols;
9516   pr "  guestfs_free_%s (r);\n" typ;
9517   pr "  return rv;\n"
9518
9519 (* Ruby code to return a struct list. *)
9520 and generate_ruby_struct_list_code typ cols =
9521   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9522   pr "  int i;\n";
9523   pr "  for (i = 0; i < r->len; ++i) {\n";
9524   pr "    VALUE hv = rb_hash_new ();\n";
9525   List.iter (
9526     function
9527     | name, FString ->
9528         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9529     | name, FBuffer ->
9530         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
9531     | name, FUUID ->
9532         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9533     | name, (FBytes|FUInt64) ->
9534         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9535     | name, FInt64 ->
9536         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9537     | name, FUInt32 ->
9538         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9539     | name, FInt32 ->
9540         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9541     | name, FOptPercent ->
9542         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9543     | name, FChar -> (* XXX wrong? *)
9544         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9545   ) cols;
9546   pr "    rb_ary_push (rv, hv);\n";
9547   pr "  }\n";
9548   pr "  guestfs_free_%s_list (r);\n" typ;
9549   pr "  return rv;\n"
9550
9551 (* Generate Java bindings GuestFS.java file. *)
9552 and generate_java_java () =
9553   generate_header CStyle LGPLv2plus;
9554
9555   pr "\
9556 package com.redhat.et.libguestfs;
9557
9558 import java.util.HashMap;
9559 import com.redhat.et.libguestfs.LibGuestFSException;
9560 import com.redhat.et.libguestfs.PV;
9561 import com.redhat.et.libguestfs.VG;
9562 import com.redhat.et.libguestfs.LV;
9563 import com.redhat.et.libguestfs.Stat;
9564 import com.redhat.et.libguestfs.StatVFS;
9565 import com.redhat.et.libguestfs.IntBool;
9566 import com.redhat.et.libguestfs.Dirent;
9567
9568 /**
9569  * The GuestFS object is a libguestfs handle.
9570  *
9571  * @author rjones
9572  */
9573 public class GuestFS {
9574   // Load the native code.
9575   static {
9576     System.loadLibrary (\"guestfs_jni\");
9577   }
9578
9579   /**
9580    * The native guestfs_h pointer.
9581    */
9582   long g;
9583
9584   /**
9585    * Create a libguestfs handle.
9586    *
9587    * @throws LibGuestFSException
9588    */
9589   public GuestFS () throws LibGuestFSException
9590   {
9591     g = _create ();
9592   }
9593   private native long _create () throws LibGuestFSException;
9594
9595   /**
9596    * Close a libguestfs handle.
9597    *
9598    * You can also leave handles to be collected by the garbage
9599    * collector, but this method ensures that the resources used
9600    * by the handle are freed up immediately.  If you call any
9601    * other methods after closing the handle, you will get an
9602    * exception.
9603    *
9604    * @throws LibGuestFSException
9605    */
9606   public void close () throws LibGuestFSException
9607   {
9608     if (g != 0)
9609       _close (g);
9610     g = 0;
9611   }
9612   private native void _close (long g) throws LibGuestFSException;
9613
9614   public void finalize () throws LibGuestFSException
9615   {
9616     close ();
9617   }
9618
9619 ";
9620
9621   List.iter (
9622     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9623       if not (List.mem NotInDocs flags); then (
9624         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9625         let doc =
9626           if List.mem ProtocolLimitWarning flags then
9627             doc ^ "\n\n" ^ protocol_limit_warning
9628           else doc in
9629         let doc =
9630           if List.mem DangerWillRobinson flags then
9631             doc ^ "\n\n" ^ danger_will_robinson
9632           else doc in
9633         let doc =
9634           match deprecation_notice flags with
9635           | None -> doc
9636           | Some txt -> doc ^ "\n\n" ^ txt in
9637         let doc = pod2text ~width:60 name doc in
9638         let doc = List.map (            (* RHBZ#501883 *)
9639           function
9640           | "" -> "<p>"
9641           | nonempty -> nonempty
9642         ) doc in
9643         let doc = String.concat "\n   * " doc in
9644
9645         pr "  /**\n";
9646         pr "   * %s\n" shortdesc;
9647         pr "   * <p>\n";
9648         pr "   * %s\n" doc;
9649         pr "   * @throws LibGuestFSException\n";
9650         pr "   */\n";
9651         pr "  ";
9652       );
9653       generate_java_prototype ~public:true ~semicolon:false name style;
9654       pr "\n";
9655       pr "  {\n";
9656       pr "    if (g == 0)\n";
9657       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9658         name;
9659       pr "    ";
9660       if fst style <> RErr then pr "return ";
9661       pr "_%s " name;
9662       generate_java_call_args ~handle:"g" (snd style);
9663       pr ";\n";
9664       pr "  }\n";
9665       pr "  ";
9666       generate_java_prototype ~privat:true ~native:true name style;
9667       pr "\n";
9668       pr "\n";
9669   ) all_functions;
9670
9671   pr "}\n"
9672
9673 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9674 and generate_java_call_args ~handle args =
9675   pr "(%s" handle;
9676   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9677   pr ")"
9678
9679 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9680     ?(semicolon=true) name style =
9681   if privat then pr "private ";
9682   if public then pr "public ";
9683   if native then pr "native ";
9684
9685   (* return type *)
9686   (match fst style with
9687    | RErr -> pr "void ";
9688    | RInt _ -> pr "int ";
9689    | RInt64 _ -> pr "long ";
9690    | RBool _ -> pr "boolean ";
9691    | RConstString _ | RConstOptString _ | RString _
9692    | RBufferOut _ -> pr "String ";
9693    | RStringList _ -> pr "String[] ";
9694    | RStruct (_, typ) ->
9695        let name = java_name_of_struct typ in
9696        pr "%s " name;
9697    | RStructList (_, typ) ->
9698        let name = java_name_of_struct typ in
9699        pr "%s[] " name;
9700    | RHashtable _ -> pr "HashMap<String,String> ";
9701   );
9702
9703   if native then pr "_%s " name else pr "%s " name;
9704   pr "(";
9705   let needs_comma = ref false in
9706   if native then (
9707     pr "long g";
9708     needs_comma := true
9709   );
9710
9711   (* args *)
9712   List.iter (
9713     fun arg ->
9714       if !needs_comma then pr ", ";
9715       needs_comma := true;
9716
9717       match arg with
9718       | Pathname n
9719       | Device n | Dev_or_Path n
9720       | String n
9721       | OptString n
9722       | FileIn n
9723       | FileOut n ->
9724           pr "String %s" n
9725       | StringList n | DeviceList n ->
9726           pr "String[] %s" n
9727       | Bool n ->
9728           pr "boolean %s" n
9729       | Int n ->
9730           pr "int %s" n
9731       | Int64 n ->
9732           pr "long %s" n
9733   ) (snd style);
9734
9735   pr ")\n";
9736   pr "    throws LibGuestFSException";
9737   if semicolon then pr ";"
9738
9739 and generate_java_struct jtyp cols () =
9740   generate_header CStyle LGPLv2plus;
9741
9742   pr "\
9743 package com.redhat.et.libguestfs;
9744
9745 /**
9746  * Libguestfs %s structure.
9747  *
9748  * @author rjones
9749  * @see GuestFS
9750  */
9751 public class %s {
9752 " jtyp jtyp;
9753
9754   List.iter (
9755     function
9756     | name, FString
9757     | name, FUUID
9758     | name, FBuffer -> pr "  public String %s;\n" name
9759     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9760     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9761     | name, FChar -> pr "  public char %s;\n" name
9762     | name, FOptPercent ->
9763         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9764         pr "  public float %s;\n" name
9765   ) cols;
9766
9767   pr "}\n"
9768
9769 and generate_java_c () =
9770   generate_header CStyle LGPLv2plus;
9771
9772   pr "\
9773 #include <stdio.h>
9774 #include <stdlib.h>
9775 #include <string.h>
9776
9777 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9778 #include \"guestfs.h\"
9779
9780 /* Note that this function returns.  The exception is not thrown
9781  * until after the wrapper function returns.
9782  */
9783 static void
9784 throw_exception (JNIEnv *env, const char *msg)
9785 {
9786   jclass cl;
9787   cl = (*env)->FindClass (env,
9788                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9789   (*env)->ThrowNew (env, cl, msg);
9790 }
9791
9792 JNIEXPORT jlong JNICALL
9793 Java_com_redhat_et_libguestfs_GuestFS__1create
9794   (JNIEnv *env, jobject obj)
9795 {
9796   guestfs_h *g;
9797
9798   g = guestfs_create ();
9799   if (g == NULL) {
9800     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9801     return 0;
9802   }
9803   guestfs_set_error_handler (g, NULL, NULL);
9804   return (jlong) (long) g;
9805 }
9806
9807 JNIEXPORT void JNICALL
9808 Java_com_redhat_et_libguestfs_GuestFS__1close
9809   (JNIEnv *env, jobject obj, jlong jg)
9810 {
9811   guestfs_h *g = (guestfs_h *) (long) jg;
9812   guestfs_close (g);
9813 }
9814
9815 ";
9816
9817   List.iter (
9818     fun (name, style, _, _, _, _, _) ->
9819       pr "JNIEXPORT ";
9820       (match fst style with
9821        | RErr -> pr "void ";
9822        | RInt _ -> pr "jint ";
9823        | RInt64 _ -> pr "jlong ";
9824        | RBool _ -> pr "jboolean ";
9825        | RConstString _ | RConstOptString _ | RString _
9826        | RBufferOut _ -> pr "jstring ";
9827        | RStruct _ | RHashtable _ ->
9828            pr "jobject ";
9829        | RStringList _ | RStructList _ ->
9830            pr "jobjectArray ";
9831       );
9832       pr "JNICALL\n";
9833       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9834       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9835       pr "\n";
9836       pr "  (JNIEnv *env, jobject obj, jlong jg";
9837       List.iter (
9838         function
9839         | Pathname n
9840         | Device n | Dev_or_Path n
9841         | String n
9842         | OptString n
9843         | FileIn n
9844         | FileOut n ->
9845             pr ", jstring j%s" n
9846         | StringList n | DeviceList n ->
9847             pr ", jobjectArray j%s" n
9848         | Bool n ->
9849             pr ", jboolean j%s" n
9850         | Int n ->
9851             pr ", jint j%s" n
9852         | Int64 n ->
9853             pr ", jlong j%s" n
9854       ) (snd style);
9855       pr ")\n";
9856       pr "{\n";
9857       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9858       let error_code, no_ret =
9859         match fst style with
9860         | RErr -> pr "  int r;\n"; "-1", ""
9861         | RBool _
9862         | RInt _ -> pr "  int r;\n"; "-1", "0"
9863         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9864         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9865         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9866         | RString _ ->
9867             pr "  jstring jr;\n";
9868             pr "  char *r;\n"; "NULL", "NULL"
9869         | RStringList _ ->
9870             pr "  jobjectArray jr;\n";
9871             pr "  int r_len;\n";
9872             pr "  jclass cl;\n";
9873             pr "  jstring jstr;\n";
9874             pr "  char **r;\n"; "NULL", "NULL"
9875         | RStruct (_, typ) ->
9876             pr "  jobject jr;\n";
9877             pr "  jclass cl;\n";
9878             pr "  jfieldID fl;\n";
9879             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9880         | RStructList (_, typ) ->
9881             pr "  jobjectArray jr;\n";
9882             pr "  jclass cl;\n";
9883             pr "  jfieldID fl;\n";
9884             pr "  jobject jfl;\n";
9885             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9886         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9887         | RBufferOut _ ->
9888             pr "  jstring jr;\n";
9889             pr "  char *r;\n";
9890             pr "  size_t size;\n";
9891             "NULL", "NULL" in
9892       List.iter (
9893         function
9894         | Pathname n
9895         | Device n | Dev_or_Path n
9896         | String n
9897         | OptString n
9898         | FileIn n
9899         | FileOut n ->
9900             pr "  const char *%s;\n" n
9901         | StringList n | DeviceList n ->
9902             pr "  int %s_len;\n" n;
9903             pr "  const char **%s;\n" n
9904         | Bool n
9905         | Int n ->
9906             pr "  int %s;\n" n
9907         | Int64 n ->
9908             pr "  int64_t %s;\n" n
9909       ) (snd style);
9910
9911       let needs_i =
9912         (match fst style with
9913          | RStringList _ | RStructList _ -> true
9914          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9915          | RConstOptString _
9916          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9917           List.exists (function
9918                        | StringList _ -> true
9919                        | DeviceList _ -> true
9920                        | _ -> false) (snd style) in
9921       if needs_i then
9922         pr "  int i;\n";
9923
9924       pr "\n";
9925
9926       (* Get the parameters. *)
9927       List.iter (
9928         function
9929         | Pathname n
9930         | Device n | Dev_or_Path n
9931         | String n
9932         | FileIn n
9933         | FileOut n ->
9934             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9935         | OptString n ->
9936             (* This is completely undocumented, but Java null becomes
9937              * a NULL parameter.
9938              *)
9939             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9940         | StringList n | DeviceList n ->
9941             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9942             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9943             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9944             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9945               n;
9946             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9947             pr "  }\n";
9948             pr "  %s[%s_len] = NULL;\n" n n;
9949         | Bool n
9950         | Int n
9951         | Int64 n ->
9952             pr "  %s = j%s;\n" n n
9953       ) (snd style);
9954
9955       (* Make the call. *)
9956       pr "  r = guestfs_%s " name;
9957       generate_c_call_args ~handle:"g" style;
9958       pr ";\n";
9959
9960       (* Release the parameters. *)
9961       List.iter (
9962         function
9963         | Pathname n
9964         | Device n | Dev_or_Path n
9965         | String n
9966         | FileIn n
9967         | FileOut n ->
9968             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9969         | OptString n ->
9970             pr "  if (j%s)\n" n;
9971             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9972         | StringList n | DeviceList n ->
9973             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9974             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9975               n;
9976             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9977             pr "  }\n";
9978             pr "  free (%s);\n" n
9979         | Bool n
9980         | Int n
9981         | Int64 n -> ()
9982       ) (snd style);
9983
9984       (* Check for errors. *)
9985       pr "  if (r == %s) {\n" error_code;
9986       pr "    throw_exception (env, guestfs_last_error (g));\n";
9987       pr "    return %s;\n" no_ret;
9988       pr "  }\n";
9989
9990       (* Return value. *)
9991       (match fst style with
9992        | RErr -> ()
9993        | RInt _ -> pr "  return (jint) r;\n"
9994        | RBool _ -> pr "  return (jboolean) r;\n"
9995        | RInt64 _ -> pr "  return (jlong) r;\n"
9996        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9997        | RConstOptString _ ->
9998            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9999        | RString _ ->
10000            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10001            pr "  free (r);\n";
10002            pr "  return jr;\n"
10003        | RStringList _ ->
10004            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10005            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10006            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10007            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10008            pr "  for (i = 0; i < r_len; ++i) {\n";
10009            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10010            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10011            pr "    free (r[i]);\n";
10012            pr "  }\n";
10013            pr "  free (r);\n";
10014            pr "  return jr;\n"
10015        | RStruct (_, typ) ->
10016            let jtyp = java_name_of_struct typ in
10017            let cols = cols_of_struct typ in
10018            generate_java_struct_return typ jtyp cols
10019        | RStructList (_, typ) ->
10020            let jtyp = java_name_of_struct typ in
10021            let cols = cols_of_struct typ in
10022            generate_java_struct_list_return typ jtyp cols
10023        | RHashtable _ ->
10024            (* XXX *)
10025            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10026            pr "  return NULL;\n"
10027        | RBufferOut _ ->
10028            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10029            pr "  free (r);\n";
10030            pr "  return jr;\n"
10031       );
10032
10033       pr "}\n";
10034       pr "\n"
10035   ) all_functions
10036
10037 and generate_java_struct_return typ jtyp cols =
10038   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10039   pr "  jr = (*env)->AllocObject (env, cl);\n";
10040   List.iter (
10041     function
10042     | name, FString ->
10043         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10044         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10045     | name, FUUID ->
10046         pr "  {\n";
10047         pr "    char s[33];\n";
10048         pr "    memcpy (s, r->%s, 32);\n" name;
10049         pr "    s[32] = 0;\n";
10050         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10051         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10052         pr "  }\n";
10053     | name, FBuffer ->
10054         pr "  {\n";
10055         pr "    int len = r->%s_len;\n" name;
10056         pr "    char s[len+1];\n";
10057         pr "    memcpy (s, r->%s, len);\n" name;
10058         pr "    s[len] = 0;\n";
10059         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10060         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10061         pr "  }\n";
10062     | name, (FBytes|FUInt64|FInt64) ->
10063         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10064         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10065     | name, (FUInt32|FInt32) ->
10066         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10067         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10068     | name, FOptPercent ->
10069         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10070         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10071     | name, FChar ->
10072         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10073         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10074   ) cols;
10075   pr "  free (r);\n";
10076   pr "  return jr;\n"
10077
10078 and generate_java_struct_list_return typ jtyp cols =
10079   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10080   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10081   pr "  for (i = 0; i < r->len; ++i) {\n";
10082   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10083   List.iter (
10084     function
10085     | name, FString ->
10086         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10087         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10088     | name, FUUID ->
10089         pr "    {\n";
10090         pr "      char s[33];\n";
10091         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10092         pr "      s[32] = 0;\n";
10093         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10094         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10095         pr "    }\n";
10096     | name, FBuffer ->
10097         pr "    {\n";
10098         pr "      int len = r->val[i].%s_len;\n" name;
10099         pr "      char s[len+1];\n";
10100         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10101         pr "      s[len] = 0;\n";
10102         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10103         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10104         pr "    }\n";
10105     | name, (FBytes|FUInt64|FInt64) ->
10106         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10107         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10108     | name, (FUInt32|FInt32) ->
10109         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10110         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10111     | name, FOptPercent ->
10112         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10113         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10114     | name, FChar ->
10115         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10116         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10117   ) cols;
10118   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10119   pr "  }\n";
10120   pr "  guestfs_free_%s_list (r);\n" typ;
10121   pr "  return jr;\n"
10122
10123 and generate_java_makefile_inc () =
10124   generate_header HashStyle GPLv2plus;
10125
10126   pr "java_built_sources = \\\n";
10127   List.iter (
10128     fun (typ, jtyp) ->
10129         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10130   ) java_structs;
10131   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10132
10133 and generate_haskell_hs () =
10134   generate_header HaskellStyle LGPLv2plus;
10135
10136   (* XXX We only know how to generate partial FFI for Haskell
10137    * at the moment.  Please help out!
10138    *)
10139   let can_generate style =
10140     match style with
10141     | RErr, _
10142     | RInt _, _
10143     | RInt64 _, _ -> true
10144     | RBool _, _
10145     | RConstString _, _
10146     | RConstOptString _, _
10147     | RString _, _
10148     | RStringList _, _
10149     | RStruct _, _
10150     | RStructList _, _
10151     | RHashtable _, _
10152     | RBufferOut _, _ -> false in
10153
10154   pr "\
10155 {-# INCLUDE <guestfs.h> #-}
10156 {-# LANGUAGE ForeignFunctionInterface #-}
10157
10158 module Guestfs (
10159   create";
10160
10161   (* List out the names of the actions we want to export. *)
10162   List.iter (
10163     fun (name, style, _, _, _, _, _) ->
10164       if can_generate style then pr ",\n  %s" name
10165   ) all_functions;
10166
10167   pr "
10168   ) where
10169
10170 -- Unfortunately some symbols duplicate ones already present
10171 -- in Prelude.  We don't know which, so we hard-code a list
10172 -- here.
10173 import Prelude hiding (truncate)
10174
10175 import Foreign
10176 import Foreign.C
10177 import Foreign.C.Types
10178 import IO
10179 import Control.Exception
10180 import Data.Typeable
10181
10182 data GuestfsS = GuestfsS            -- represents the opaque C struct
10183 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10184 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10185
10186 -- XXX define properly later XXX
10187 data PV = PV
10188 data VG = VG
10189 data LV = LV
10190 data IntBool = IntBool
10191 data Stat = Stat
10192 data StatVFS = StatVFS
10193 data Hashtable = Hashtable
10194
10195 foreign import ccall unsafe \"guestfs_create\" c_create
10196   :: IO GuestfsP
10197 foreign import ccall unsafe \"&guestfs_close\" c_close
10198   :: FunPtr (GuestfsP -> IO ())
10199 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10200   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10201
10202 create :: IO GuestfsH
10203 create = do
10204   p <- c_create
10205   c_set_error_handler p nullPtr nullPtr
10206   h <- newForeignPtr c_close p
10207   return h
10208
10209 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10210   :: GuestfsP -> IO CString
10211
10212 -- last_error :: GuestfsH -> IO (Maybe String)
10213 -- last_error h = do
10214 --   str <- withForeignPtr h (\\p -> c_last_error p)
10215 --   maybePeek peekCString str
10216
10217 last_error :: GuestfsH -> IO (String)
10218 last_error h = do
10219   str <- withForeignPtr h (\\p -> c_last_error p)
10220   if (str == nullPtr)
10221     then return \"no error\"
10222     else peekCString str
10223
10224 ";
10225
10226   (* Generate wrappers for each foreign function. *)
10227   List.iter (
10228     fun (name, style, _, _, _, _, _) ->
10229       if can_generate style then (
10230         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10231         pr "  :: ";
10232         generate_haskell_prototype ~handle:"GuestfsP" style;
10233         pr "\n";
10234         pr "\n";
10235         pr "%s :: " name;
10236         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10237         pr "\n";
10238         pr "%s %s = do\n" name
10239           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10240         pr "  r <- ";
10241         (* Convert pointer arguments using with* functions. *)
10242         List.iter (
10243           function
10244           | FileIn n
10245           | FileOut n
10246           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10247           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10248           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10249           | Bool _ | Int _ | Int64 _ -> ()
10250         ) (snd style);
10251         (* Convert integer arguments. *)
10252         let args =
10253           List.map (
10254             function
10255             | Bool n -> sprintf "(fromBool %s)" n
10256             | Int n -> sprintf "(fromIntegral %s)" n
10257             | Int64 n -> sprintf "(fromIntegral %s)" n
10258             | FileIn n | FileOut n
10259             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10260           ) (snd style) in
10261         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10262           (String.concat " " ("p" :: args));
10263         (match fst style with
10264          | RErr | RInt _ | RInt64 _ | RBool _ ->
10265              pr "  if (r == -1)\n";
10266              pr "    then do\n";
10267              pr "      err <- last_error h\n";
10268              pr "      fail err\n";
10269          | RConstString _ | RConstOptString _ | RString _
10270          | RStringList _ | RStruct _
10271          | RStructList _ | RHashtable _ | RBufferOut _ ->
10272              pr "  if (r == nullPtr)\n";
10273              pr "    then do\n";
10274              pr "      err <- last_error h\n";
10275              pr "      fail err\n";
10276         );
10277         (match fst style with
10278          | RErr ->
10279              pr "    else return ()\n"
10280          | RInt _ ->
10281              pr "    else return (fromIntegral r)\n"
10282          | RInt64 _ ->
10283              pr "    else return (fromIntegral r)\n"
10284          | RBool _ ->
10285              pr "    else return (toBool r)\n"
10286          | RConstString _
10287          | RConstOptString _
10288          | RString _
10289          | RStringList _
10290          | RStruct _
10291          | RStructList _
10292          | RHashtable _
10293          | RBufferOut _ ->
10294              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10295         );
10296         pr "\n";
10297       )
10298   ) all_functions
10299
10300 and generate_haskell_prototype ~handle ?(hs = false) style =
10301   pr "%s -> " handle;
10302   let string = if hs then "String" else "CString" in
10303   let int = if hs then "Int" else "CInt" in
10304   let bool = if hs then "Bool" else "CInt" in
10305   let int64 = if hs then "Integer" else "Int64" in
10306   List.iter (
10307     fun arg ->
10308       (match arg with
10309        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10310        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10311        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10312        | Bool _ -> pr "%s" bool
10313        | Int _ -> pr "%s" int
10314        | Int64 _ -> pr "%s" int
10315        | FileIn _ -> pr "%s" string
10316        | FileOut _ -> pr "%s" string
10317       );
10318       pr " -> ";
10319   ) (snd style);
10320   pr "IO (";
10321   (match fst style with
10322    | RErr -> if not hs then pr "CInt"
10323    | RInt _ -> pr "%s" int
10324    | RInt64 _ -> pr "%s" int64
10325    | RBool _ -> pr "%s" bool
10326    | RConstString _ -> pr "%s" string
10327    | RConstOptString _ -> pr "Maybe %s" string
10328    | RString _ -> pr "%s" string
10329    | RStringList _ -> pr "[%s]" string
10330    | RStruct (_, typ) ->
10331        let name = java_name_of_struct typ in
10332        pr "%s" name
10333    | RStructList (_, typ) ->
10334        let name = java_name_of_struct typ in
10335        pr "[%s]" name
10336    | RHashtable _ -> pr "Hashtable"
10337    | RBufferOut _ -> pr "%s" string
10338   );
10339   pr ")"
10340
10341 and generate_csharp () =
10342   generate_header CPlusPlusStyle LGPLv2plus;
10343
10344   (* XXX Make this configurable by the C# assembly users. *)
10345   let library = "libguestfs.so.0" in
10346
10347   pr "\
10348 // These C# bindings are highly experimental at present.
10349 //
10350 // Firstly they only work on Linux (ie. Mono).  In order to get them
10351 // to work on Windows (ie. .Net) you would need to port the library
10352 // itself to Windows first.
10353 //
10354 // The second issue is that some calls are known to be incorrect and
10355 // can cause Mono to segfault.  Particularly: calls which pass or
10356 // return string[], or return any structure value.  This is because
10357 // we haven't worked out the correct way to do this from C#.
10358 //
10359 // The third issue is that when compiling you get a lot of warnings.
10360 // We are not sure whether the warnings are important or not.
10361 //
10362 // Fourthly we do not routinely build or test these bindings as part
10363 // of the make && make check cycle, which means that regressions might
10364 // go unnoticed.
10365 //
10366 // Suggestions and patches are welcome.
10367
10368 // To compile:
10369 //
10370 // gmcs Libguestfs.cs
10371 // mono Libguestfs.exe
10372 //
10373 // (You'll probably want to add a Test class / static main function
10374 // otherwise this won't do anything useful).
10375
10376 using System;
10377 using System.IO;
10378 using System.Runtime.InteropServices;
10379 using System.Runtime.Serialization;
10380 using System.Collections;
10381
10382 namespace Guestfs
10383 {
10384   class Error : System.ApplicationException
10385   {
10386     public Error (string message) : base (message) {}
10387     protected Error (SerializationInfo info, StreamingContext context) {}
10388   }
10389
10390   class Guestfs
10391   {
10392     IntPtr _handle;
10393
10394     [DllImport (\"%s\")]
10395     static extern IntPtr guestfs_create ();
10396
10397     public Guestfs ()
10398     {
10399       _handle = guestfs_create ();
10400       if (_handle == IntPtr.Zero)
10401         throw new Error (\"could not create guestfs handle\");
10402     }
10403
10404     [DllImport (\"%s\")]
10405     static extern void guestfs_close (IntPtr h);
10406
10407     ~Guestfs ()
10408     {
10409       guestfs_close (_handle);
10410     }
10411
10412     [DllImport (\"%s\")]
10413     static extern string guestfs_last_error (IntPtr h);
10414
10415 " library library library;
10416
10417   (* Generate C# structure bindings.  We prefix struct names with
10418    * underscore because C# cannot have conflicting struct names and
10419    * method names (eg. "class stat" and "stat").
10420    *)
10421   List.iter (
10422     fun (typ, cols) ->
10423       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10424       pr "    public class _%s {\n" typ;
10425       List.iter (
10426         function
10427         | name, FChar -> pr "      char %s;\n" name
10428         | name, FString -> pr "      string %s;\n" name
10429         | name, FBuffer ->
10430             pr "      uint %s_len;\n" name;
10431             pr "      string %s;\n" name
10432         | name, FUUID ->
10433             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10434             pr "      string %s;\n" name
10435         | name, FUInt32 -> pr "      uint %s;\n" name
10436         | name, FInt32 -> pr "      int %s;\n" name
10437         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10438         | name, FInt64 -> pr "      long %s;\n" name
10439         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10440       ) cols;
10441       pr "    }\n";
10442       pr "\n"
10443   ) structs;
10444
10445   (* Generate C# function bindings. *)
10446   List.iter (
10447     fun (name, style, _, _, _, shortdesc, _) ->
10448       let rec csharp_return_type () =
10449         match fst style with
10450         | RErr -> "void"
10451         | RBool n -> "bool"
10452         | RInt n -> "int"
10453         | RInt64 n -> "long"
10454         | RConstString n
10455         | RConstOptString n
10456         | RString n
10457         | RBufferOut n -> "string"
10458         | RStruct (_,n) -> "_" ^ n
10459         | RHashtable n -> "Hashtable"
10460         | RStringList n -> "string[]"
10461         | RStructList (_,n) -> sprintf "_%s[]" n
10462
10463       and c_return_type () =
10464         match fst style with
10465         | RErr
10466         | RBool _
10467         | RInt _ -> "int"
10468         | RInt64 _ -> "long"
10469         | RConstString _
10470         | RConstOptString _
10471         | RString _
10472         | RBufferOut _ -> "string"
10473         | RStruct (_,n) -> "_" ^ n
10474         | RHashtable _
10475         | RStringList _ -> "string[]"
10476         | RStructList (_,n) -> sprintf "_%s[]" n
10477
10478       and c_error_comparison () =
10479         match fst style with
10480         | RErr
10481         | RBool _
10482         | RInt _
10483         | RInt64 _ -> "== -1"
10484         | RConstString _
10485         | RConstOptString _
10486         | RString _
10487         | RBufferOut _
10488         | RStruct (_,_)
10489         | RHashtable _
10490         | RStringList _
10491         | RStructList (_,_) -> "== null"
10492
10493       and generate_extern_prototype () =
10494         pr "    static extern %s guestfs_%s (IntPtr h"
10495           (c_return_type ()) name;
10496         List.iter (
10497           function
10498           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10499           | FileIn n | FileOut n ->
10500               pr ", [In] string %s" n
10501           | StringList n | DeviceList n ->
10502               pr ", [In] string[] %s" n
10503           | Bool n ->
10504               pr ", bool %s" n
10505           | Int n ->
10506               pr ", int %s" n
10507           | Int64 n ->
10508               pr ", long %s" n
10509         ) (snd style);
10510         pr ");\n"
10511
10512       and generate_public_prototype () =
10513         pr "    public %s %s (" (csharp_return_type ()) name;
10514         let comma = ref false in
10515         let next () =
10516           if !comma then pr ", ";
10517           comma := true
10518         in
10519         List.iter (
10520           function
10521           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10522           | FileIn n | FileOut n ->
10523               next (); pr "string %s" n
10524           | StringList n | DeviceList n ->
10525               next (); pr "string[] %s" n
10526           | Bool n ->
10527               next (); pr "bool %s" n
10528           | Int n ->
10529               next (); pr "int %s" n
10530           | Int64 n ->
10531               next (); pr "long %s" n
10532         ) (snd style);
10533         pr ")\n"
10534
10535       and generate_call () =
10536         pr "guestfs_%s (_handle" name;
10537         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10538         pr ");\n";
10539       in
10540
10541       pr "    [DllImport (\"%s\")]\n" library;
10542       generate_extern_prototype ();
10543       pr "\n";
10544       pr "    /// <summary>\n";
10545       pr "    /// %s\n" shortdesc;
10546       pr "    /// </summary>\n";
10547       generate_public_prototype ();
10548       pr "    {\n";
10549       pr "      %s r;\n" (c_return_type ());
10550       pr "      r = ";
10551       generate_call ();
10552       pr "      if (r %s)\n" (c_error_comparison ());
10553       pr "        throw new Error (guestfs_last_error (_handle));\n";
10554       (match fst style with
10555        | RErr -> ()
10556        | RBool _ ->
10557            pr "      return r != 0 ? true : false;\n"
10558        | RHashtable _ ->
10559            pr "      Hashtable rr = new Hashtable ();\n";
10560            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10561            pr "        rr.Add (r[i], r[i+1]);\n";
10562            pr "      return rr;\n"
10563        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10564        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10565        | RStructList _ ->
10566            pr "      return r;\n"
10567       );
10568       pr "    }\n";
10569       pr "\n";
10570   ) all_functions_sorted;
10571
10572   pr "  }
10573 }
10574 "
10575
10576 and generate_bindtests () =
10577   generate_header CStyle LGPLv2plus;
10578
10579   pr "\
10580 #include <stdio.h>
10581 #include <stdlib.h>
10582 #include <inttypes.h>
10583 #include <string.h>
10584
10585 #include \"guestfs.h\"
10586 #include \"guestfs-internal.h\"
10587 #include \"guestfs-internal-actions.h\"
10588 #include \"guestfs_protocol.h\"
10589
10590 #define error guestfs_error
10591 #define safe_calloc guestfs_safe_calloc
10592 #define safe_malloc guestfs_safe_malloc
10593
10594 static void
10595 print_strings (char *const *argv)
10596 {
10597   int argc;
10598
10599   printf (\"[\");
10600   for (argc = 0; argv[argc] != NULL; ++argc) {
10601     if (argc > 0) printf (\", \");
10602     printf (\"\\\"%%s\\\"\", argv[argc]);
10603   }
10604   printf (\"]\\n\");
10605 }
10606
10607 /* The test0 function prints its parameters to stdout. */
10608 ";
10609
10610   let test0, tests =
10611     match test_functions with
10612     | [] -> assert false
10613     | test0 :: tests -> test0, tests in
10614
10615   let () =
10616     let (name, style, _, _, _, _, _) = test0 in
10617     generate_prototype ~extern:false ~semicolon:false ~newline:true
10618       ~handle:"g" ~prefix:"guestfs__" name style;
10619     pr "{\n";
10620     List.iter (
10621       function
10622       | Pathname n
10623       | Device n | Dev_or_Path n
10624       | String n
10625       | FileIn n
10626       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10627       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10628       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10629       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10630       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10631       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10632     ) (snd style);
10633     pr "  /* Java changes stdout line buffering so we need this: */\n";
10634     pr "  fflush (stdout);\n";
10635     pr "  return 0;\n";
10636     pr "}\n";
10637     pr "\n" in
10638
10639   List.iter (
10640     fun (name, style, _, _, _, _, _) ->
10641       if String.sub name (String.length name - 3) 3 <> "err" then (
10642         pr "/* Test normal return. */\n";
10643         generate_prototype ~extern:false ~semicolon:false ~newline:true
10644           ~handle:"g" ~prefix:"guestfs__" name style;
10645         pr "{\n";
10646         (match fst style with
10647          | RErr ->
10648              pr "  return 0;\n"
10649          | RInt _ ->
10650              pr "  int r;\n";
10651              pr "  sscanf (val, \"%%d\", &r);\n";
10652              pr "  return r;\n"
10653          | RInt64 _ ->
10654              pr "  int64_t r;\n";
10655              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10656              pr "  return r;\n"
10657          | RBool _ ->
10658              pr "  return STREQ (val, \"true\");\n"
10659          | RConstString _
10660          | RConstOptString _ ->
10661              (* Can't return the input string here.  Return a static
10662               * string so we ensure we get a segfault if the caller
10663               * tries to free it.
10664               *)
10665              pr "  return \"static string\";\n"
10666          | RString _ ->
10667              pr "  return strdup (val);\n"
10668          | RStringList _ ->
10669              pr "  char **strs;\n";
10670              pr "  int n, i;\n";
10671              pr "  sscanf (val, \"%%d\", &n);\n";
10672              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10673              pr "  for (i = 0; i < n; ++i) {\n";
10674              pr "    strs[i] = safe_malloc (g, 16);\n";
10675              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10676              pr "  }\n";
10677              pr "  strs[n] = NULL;\n";
10678              pr "  return strs;\n"
10679          | RStruct (_, typ) ->
10680              pr "  struct guestfs_%s *r;\n" typ;
10681              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10682              pr "  return r;\n"
10683          | RStructList (_, typ) ->
10684              pr "  struct guestfs_%s_list *r;\n" typ;
10685              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10686              pr "  sscanf (val, \"%%d\", &r->len);\n";
10687              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10688              pr "  return r;\n"
10689          | RHashtable _ ->
10690              pr "  char **strs;\n";
10691              pr "  int n, i;\n";
10692              pr "  sscanf (val, \"%%d\", &n);\n";
10693              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10694              pr "  for (i = 0; i < n; ++i) {\n";
10695              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10696              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10697              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10698              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10699              pr "  }\n";
10700              pr "  strs[n*2] = NULL;\n";
10701              pr "  return strs;\n"
10702          | RBufferOut _ ->
10703              pr "  return strdup (val);\n"
10704         );
10705         pr "}\n";
10706         pr "\n"
10707       ) else (
10708         pr "/* Test error return. */\n";
10709         generate_prototype ~extern:false ~semicolon:false ~newline:true
10710           ~handle:"g" ~prefix:"guestfs__" name style;
10711         pr "{\n";
10712         pr "  error (g, \"error\");\n";
10713         (match fst style with
10714          | RErr | RInt _ | RInt64 _ | RBool _ ->
10715              pr "  return -1;\n"
10716          | RConstString _ | RConstOptString _
10717          | RString _ | RStringList _ | RStruct _
10718          | RStructList _
10719          | RHashtable _
10720          | RBufferOut _ ->
10721              pr "  return NULL;\n"
10722         );
10723         pr "}\n";
10724         pr "\n"
10725       )
10726   ) tests
10727
10728 and generate_ocaml_bindtests () =
10729   generate_header OCamlStyle GPLv2plus;
10730
10731   pr "\
10732 let () =
10733   let g = Guestfs.create () in
10734 ";
10735
10736   let mkargs args =
10737     String.concat " " (
10738       List.map (
10739         function
10740         | CallString s -> "\"" ^ s ^ "\""
10741         | CallOptString None -> "None"
10742         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10743         | CallStringList xs ->
10744             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10745         | CallInt i when i >= 0 -> string_of_int i
10746         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10747         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10748         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10749         | CallBool b -> string_of_bool b
10750       ) args
10751     )
10752   in
10753
10754   generate_lang_bindtests (
10755     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10756   );
10757
10758   pr "print_endline \"EOF\"\n"
10759
10760 and generate_perl_bindtests () =
10761   pr "#!/usr/bin/perl -w\n";
10762   generate_header HashStyle GPLv2plus;
10763
10764   pr "\
10765 use strict;
10766
10767 use Sys::Guestfs;
10768
10769 my $g = Sys::Guestfs->new ();
10770 ";
10771
10772   let mkargs args =
10773     String.concat ", " (
10774       List.map (
10775         function
10776         | CallString s -> "\"" ^ s ^ "\""
10777         | CallOptString None -> "undef"
10778         | CallOptString (Some s) -> sprintf "\"%s\"" s
10779         | CallStringList xs ->
10780             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10781         | CallInt i -> string_of_int i
10782         | CallInt64 i -> Int64.to_string i
10783         | CallBool b -> if b then "1" else "0"
10784       ) args
10785     )
10786   in
10787
10788   generate_lang_bindtests (
10789     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10790   );
10791
10792   pr "print \"EOF\\n\"\n"
10793
10794 and generate_python_bindtests () =
10795   generate_header HashStyle GPLv2plus;
10796
10797   pr "\
10798 import guestfs
10799
10800 g = guestfs.GuestFS ()
10801 ";
10802
10803   let mkargs args =
10804     String.concat ", " (
10805       List.map (
10806         function
10807         | CallString s -> "\"" ^ s ^ "\""
10808         | CallOptString None -> "None"
10809         | CallOptString (Some s) -> sprintf "\"%s\"" s
10810         | CallStringList xs ->
10811             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10812         | CallInt i -> string_of_int i
10813         | CallInt64 i -> Int64.to_string i
10814         | CallBool b -> if b then "1" else "0"
10815       ) args
10816     )
10817   in
10818
10819   generate_lang_bindtests (
10820     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10821   );
10822
10823   pr "print \"EOF\"\n"
10824
10825 and generate_ruby_bindtests () =
10826   generate_header HashStyle GPLv2plus;
10827
10828   pr "\
10829 require 'guestfs'
10830
10831 g = Guestfs::create()
10832 ";
10833
10834   let mkargs args =
10835     String.concat ", " (
10836       List.map (
10837         function
10838         | CallString s -> "\"" ^ s ^ "\""
10839         | CallOptString None -> "nil"
10840         | CallOptString (Some s) -> sprintf "\"%s\"" s
10841         | CallStringList xs ->
10842             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10843         | CallInt i -> string_of_int i
10844         | CallInt64 i -> Int64.to_string i
10845         | CallBool b -> string_of_bool b
10846       ) args
10847     )
10848   in
10849
10850   generate_lang_bindtests (
10851     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10852   );
10853
10854   pr "print \"EOF\\n\"\n"
10855
10856 and generate_java_bindtests () =
10857   generate_header CStyle GPLv2plus;
10858
10859   pr "\
10860 import com.redhat.et.libguestfs.*;
10861
10862 public class Bindtests {
10863     public static void main (String[] argv)
10864     {
10865         try {
10866             GuestFS g = new GuestFS ();
10867 ";
10868
10869   let mkargs args =
10870     String.concat ", " (
10871       List.map (
10872         function
10873         | CallString s -> "\"" ^ s ^ "\""
10874         | CallOptString None -> "null"
10875         | CallOptString (Some s) -> sprintf "\"%s\"" s
10876         | CallStringList xs ->
10877             "new String[]{" ^
10878               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10879         | CallInt i -> string_of_int i
10880         | CallInt64 i -> Int64.to_string i
10881         | CallBool b -> string_of_bool b
10882       ) args
10883     )
10884   in
10885
10886   generate_lang_bindtests (
10887     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10888   );
10889
10890   pr "
10891             System.out.println (\"EOF\");
10892         }
10893         catch (Exception exn) {
10894             System.err.println (exn);
10895             System.exit (1);
10896         }
10897     }
10898 }
10899 "
10900
10901 and generate_haskell_bindtests () =
10902   generate_header HaskellStyle GPLv2plus;
10903
10904   pr "\
10905 module Bindtests where
10906 import qualified Guestfs
10907
10908 main = do
10909   g <- Guestfs.create
10910 ";
10911
10912   let mkargs args =
10913     String.concat " " (
10914       List.map (
10915         function
10916         | CallString s -> "\"" ^ s ^ "\""
10917         | CallOptString None -> "Nothing"
10918         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10919         | CallStringList xs ->
10920             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10921         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10922         | CallInt i -> string_of_int i
10923         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10924         | CallInt64 i -> Int64.to_string i
10925         | CallBool true -> "True"
10926         | CallBool false -> "False"
10927       ) args
10928     )
10929   in
10930
10931   generate_lang_bindtests (
10932     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10933   );
10934
10935   pr "  putStrLn \"EOF\"\n"
10936
10937 (* Language-independent bindings tests - we do it this way to
10938  * ensure there is parity in testing bindings across all languages.
10939  *)
10940 and generate_lang_bindtests call =
10941   call "test0" [CallString "abc"; CallOptString (Some "def");
10942                 CallStringList []; CallBool false;
10943                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10944   call "test0" [CallString "abc"; CallOptString None;
10945                 CallStringList []; CallBool false;
10946                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10947   call "test0" [CallString ""; CallOptString (Some "def");
10948                 CallStringList []; CallBool false;
10949                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10950   call "test0" [CallString ""; CallOptString (Some "");
10951                 CallStringList []; CallBool false;
10952                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10953   call "test0" [CallString "abc"; CallOptString (Some "def");
10954                 CallStringList ["1"]; CallBool false;
10955                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10956   call "test0" [CallString "abc"; CallOptString (Some "def");
10957                 CallStringList ["1"; "2"]; CallBool false;
10958                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10959   call "test0" [CallString "abc"; CallOptString (Some "def");
10960                 CallStringList ["1"]; CallBool true;
10961                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10962   call "test0" [CallString "abc"; CallOptString (Some "def");
10963                 CallStringList ["1"]; CallBool false;
10964                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10965   call "test0" [CallString "abc"; CallOptString (Some "def");
10966                 CallStringList ["1"]; CallBool false;
10967                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10968   call "test0" [CallString "abc"; CallOptString (Some "def");
10969                 CallStringList ["1"]; CallBool false;
10970                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10971   call "test0" [CallString "abc"; CallOptString (Some "def");
10972                 CallStringList ["1"]; CallBool false;
10973                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10974   call "test0" [CallString "abc"; CallOptString (Some "def");
10975                 CallStringList ["1"]; CallBool false;
10976                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10977   call "test0" [CallString "abc"; CallOptString (Some "def");
10978                 CallStringList ["1"]; CallBool false;
10979                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10980
10981 (* XXX Add here tests of the return and error functions. *)
10982
10983 (* Code to generator bindings for virt-inspector.  Currently only
10984  * implemented for OCaml code (for virt-p2v 2.0).
10985  *)
10986 let rng_input = "inspector/virt-inspector.rng"
10987
10988 (* Read the input file and parse it into internal structures.  This is
10989  * by no means a complete RELAX NG parser, but is just enough to be
10990  * able to parse the specific input file.
10991  *)
10992 type rng =
10993   | Element of string * rng list        (* <element name=name/> *)
10994   | Attribute of string * rng list        (* <attribute name=name/> *)
10995   | Interleave of rng list                (* <interleave/> *)
10996   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10997   | OneOrMore of rng                        (* <oneOrMore/> *)
10998   | Optional of rng                        (* <optional/> *)
10999   | Choice of string list                (* <choice><value/>*</choice> *)
11000   | Value of string                        (* <value>str</value> *)
11001   | Text                                (* <text/> *)
11002
11003 let rec string_of_rng = function
11004   | Element (name, xs) ->
11005       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11006   | Attribute (name, xs) ->
11007       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11008   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11009   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11010   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11011   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11012   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11013   | Value value -> "Value \"" ^ value ^ "\""
11014   | Text -> "Text"
11015
11016 and string_of_rng_list xs =
11017   String.concat ", " (List.map string_of_rng xs)
11018
11019 let rec parse_rng ?defines context = function
11020   | [] -> []
11021   | Xml.Element ("element", ["name", name], children) :: rest ->
11022       Element (name, parse_rng ?defines context children)
11023       :: parse_rng ?defines context rest
11024   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11025       Attribute (name, parse_rng ?defines context children)
11026       :: parse_rng ?defines context rest
11027   | Xml.Element ("interleave", [], children) :: rest ->
11028       Interleave (parse_rng ?defines context children)
11029       :: parse_rng ?defines context rest
11030   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11031       let rng = parse_rng ?defines context [child] in
11032       (match rng with
11033        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11034        | _ ->
11035            failwithf "%s: <zeroOrMore> contains more than one child element"
11036              context
11037       )
11038   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11039       let rng = parse_rng ?defines context [child] in
11040       (match rng with
11041        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11042        | _ ->
11043            failwithf "%s: <oneOrMore> contains more than one child element"
11044              context
11045       )
11046   | Xml.Element ("optional", [], [child]) :: rest ->
11047       let rng = parse_rng ?defines context [child] in
11048       (match rng with
11049        | [child] -> Optional child :: parse_rng ?defines context rest
11050        | _ ->
11051            failwithf "%s: <optional> contains more than one child element"
11052              context
11053       )
11054   | Xml.Element ("choice", [], children) :: rest ->
11055       let values = List.map (
11056         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11057         | _ ->
11058             failwithf "%s: can't handle anything except <value> in <choice>"
11059               context
11060       ) children in
11061       Choice values
11062       :: parse_rng ?defines context rest
11063   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11064       Value value :: parse_rng ?defines context rest
11065   | Xml.Element ("text", [], []) :: rest ->
11066       Text :: parse_rng ?defines context rest
11067   | Xml.Element ("ref", ["name", name], []) :: rest ->
11068       (* Look up the reference.  Because of limitations in this parser,
11069        * we can't handle arbitrarily nested <ref> yet.  You can only
11070        * use <ref> from inside <start>.
11071        *)
11072       (match defines with
11073        | None ->
11074            failwithf "%s: contains <ref>, but no refs are defined yet" context
11075        | Some map ->
11076            let rng = StringMap.find name map in
11077            rng @ parse_rng ?defines context rest
11078       )
11079   | x :: _ ->
11080       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11081
11082 let grammar =
11083   let xml = Xml.parse_file rng_input in
11084   match xml with
11085   | Xml.Element ("grammar", _,
11086                  Xml.Element ("start", _, gram) :: defines) ->
11087       (* The <define/> elements are referenced in the <start> section,
11088        * so build a map of those first.
11089        *)
11090       let defines = List.fold_left (
11091         fun map ->
11092           function Xml.Element ("define", ["name", name], defn) ->
11093             StringMap.add name defn map
11094           | _ ->
11095               failwithf "%s: expected <define name=name/>" rng_input
11096       ) StringMap.empty defines in
11097       let defines = StringMap.mapi parse_rng defines in
11098
11099       (* Parse the <start> clause, passing the defines. *)
11100       parse_rng ~defines "<start>" gram
11101   | _ ->
11102       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11103         rng_input
11104
11105 let name_of_field = function
11106   | Element (name, _) | Attribute (name, _)
11107   | ZeroOrMore (Element (name, _))
11108   | OneOrMore (Element (name, _))
11109   | Optional (Element (name, _)) -> name
11110   | Optional (Attribute (name, _)) -> name
11111   | Text -> (* an unnamed field in an element *)
11112       "data"
11113   | rng ->
11114       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11115
11116 (* At the moment this function only generates OCaml types.  However we
11117  * should parameterize it later so it can generate types/structs in a
11118  * variety of languages.
11119  *)
11120 let generate_types xs =
11121   (* A simple type is one that can be printed out directly, eg.
11122    * "string option".  A complex type is one which has a name and has
11123    * to be defined via another toplevel definition, eg. a struct.
11124    *
11125    * generate_type generates code for either simple or complex types.
11126    * In the simple case, it returns the string ("string option").  In
11127    * the complex case, it returns the name ("mountpoint").  In the
11128    * complex case it has to print out the definition before returning,
11129    * so it should only be called when we are at the beginning of a
11130    * new line (BOL context).
11131    *)
11132   let rec generate_type = function
11133     | Text ->                                (* string *)
11134         "string", true
11135     | Choice values ->                        (* [`val1|`val2|...] *)
11136         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11137     | ZeroOrMore rng ->                        (* <rng> list *)
11138         let t, is_simple = generate_type rng in
11139         t ^ " list (* 0 or more *)", is_simple
11140     | OneOrMore rng ->                        (* <rng> list *)
11141         let t, is_simple = generate_type rng in
11142         t ^ " list (* 1 or more *)", is_simple
11143                                         (* virt-inspector hack: bool *)
11144     | Optional (Attribute (name, [Value "1"])) ->
11145         "bool", true
11146     | Optional rng ->                        (* <rng> list *)
11147         let t, is_simple = generate_type rng in
11148         t ^ " option", is_simple
11149                                         (* type name = { fields ... } *)
11150     | Element (name, fields) when is_attrs_interleave fields ->
11151         generate_type_struct name (get_attrs_interleave fields)
11152     | Element (name, [field])                (* type name = field *)
11153     | Attribute (name, [field]) ->
11154         let t, is_simple = generate_type field in
11155         if is_simple then (t, true)
11156         else (
11157           pr "type %s = %s\n" name t;
11158           name, false
11159         )
11160     | Element (name, fields) ->              (* type name = { fields ... } *)
11161         generate_type_struct name fields
11162     | rng ->
11163         failwithf "generate_type failed at: %s" (string_of_rng rng)
11164
11165   and is_attrs_interleave = function
11166     | [Interleave _] -> true
11167     | Attribute _ :: fields -> is_attrs_interleave fields
11168     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11169     | _ -> false
11170
11171   and get_attrs_interleave = function
11172     | [Interleave fields] -> fields
11173     | ((Attribute _) as field) :: fields
11174     | ((Optional (Attribute _)) as field) :: fields ->
11175         field :: get_attrs_interleave fields
11176     | _ -> assert false
11177
11178   and generate_types xs =
11179     List.iter (fun x -> ignore (generate_type x)) xs
11180
11181   and generate_type_struct name fields =
11182     (* Calculate the types of the fields first.  We have to do this
11183      * before printing anything so we are still in BOL context.
11184      *)
11185     let types = List.map fst (List.map generate_type fields) in
11186
11187     (* Special case of a struct containing just a string and another
11188      * field.  Turn it into an assoc list.
11189      *)
11190     match types with
11191     | ["string"; other] ->
11192         let fname1, fname2 =
11193           match fields with
11194           | [f1; f2] -> name_of_field f1, name_of_field f2
11195           | _ -> assert false in
11196         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11197         name, false
11198
11199     | types ->
11200         pr "type %s = {\n" name;
11201         List.iter (
11202           fun (field, ftype) ->
11203             let fname = name_of_field field in
11204             pr "  %s_%s : %s;\n" name fname ftype
11205         ) (List.combine fields types);
11206         pr "}\n";
11207         (* Return the name of this type, and
11208          * false because it's not a simple type.
11209          *)
11210         name, false
11211   in
11212
11213   generate_types xs
11214
11215 let generate_parsers xs =
11216   (* As for generate_type above, generate_parser makes a parser for
11217    * some type, and returns the name of the parser it has generated.
11218    * Because it (may) need to print something, it should always be
11219    * called in BOL context.
11220    *)
11221   let rec generate_parser = function
11222     | Text ->                                (* string *)
11223         "string_child_or_empty"
11224     | Choice values ->                        (* [`val1|`val2|...] *)
11225         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11226           (String.concat "|"
11227              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11228     | ZeroOrMore rng ->                        (* <rng> list *)
11229         let pa = generate_parser rng in
11230         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11231     | OneOrMore rng ->                        (* <rng> list *)
11232         let pa = generate_parser rng in
11233         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11234                                         (* virt-inspector hack: bool *)
11235     | Optional (Attribute (name, [Value "1"])) ->
11236         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11237     | Optional rng ->                        (* <rng> list *)
11238         let pa = generate_parser rng in
11239         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11240                                         (* type name = { fields ... } *)
11241     | Element (name, fields) when is_attrs_interleave fields ->
11242         generate_parser_struct name (get_attrs_interleave fields)
11243     | Element (name, [field]) ->        (* type name = field *)
11244         let pa = generate_parser field in
11245         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11246         pr "let %s =\n" parser_name;
11247         pr "  %s\n" pa;
11248         pr "let parse_%s = %s\n" name parser_name;
11249         parser_name
11250     | Attribute (name, [field]) ->
11251         let pa = generate_parser field in
11252         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11253         pr "let %s =\n" parser_name;
11254         pr "  %s\n" pa;
11255         pr "let parse_%s = %s\n" name parser_name;
11256         parser_name
11257     | Element (name, fields) ->              (* type name = { fields ... } *)
11258         generate_parser_struct name ([], fields)
11259     | rng ->
11260         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11261
11262   and is_attrs_interleave = function
11263     | [Interleave _] -> true
11264     | Attribute _ :: fields -> is_attrs_interleave fields
11265     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11266     | _ -> false
11267
11268   and get_attrs_interleave = function
11269     | [Interleave fields] -> [], fields
11270     | ((Attribute _) as field) :: fields
11271     | ((Optional (Attribute _)) as field) :: fields ->
11272         let attrs, interleaves = get_attrs_interleave fields in
11273         (field :: attrs), interleaves
11274     | _ -> assert false
11275
11276   and generate_parsers xs =
11277     List.iter (fun x -> ignore (generate_parser x)) xs
11278
11279   and generate_parser_struct name (attrs, interleaves) =
11280     (* Generate parsers for the fields first.  We have to do this
11281      * before printing anything so we are still in BOL context.
11282      *)
11283     let fields = attrs @ interleaves in
11284     let pas = List.map generate_parser fields in
11285
11286     (* Generate an intermediate tuple from all the fields first.
11287      * If the type is just a string + another field, then we will
11288      * return this directly, otherwise it is turned into a record.
11289      *
11290      * RELAX NG note: This code treats <interleave> and plain lists of
11291      * fields the same.  In other words, it doesn't bother enforcing
11292      * any ordering of fields in the XML.
11293      *)
11294     pr "let parse_%s x =\n" name;
11295     pr "  let t = (\n    ";
11296     let comma = ref false in
11297     List.iter (
11298       fun x ->
11299         if !comma then pr ",\n    ";
11300         comma := true;
11301         match x with
11302         | Optional (Attribute (fname, [field])), pa ->
11303             pr "%s x" pa
11304         | Optional (Element (fname, [field])), pa ->
11305             pr "%s (optional_child %S x)" pa fname
11306         | Attribute (fname, [Text]), _ ->
11307             pr "attribute %S x" fname
11308         | (ZeroOrMore _ | OneOrMore _), pa ->
11309             pr "%s x" pa
11310         | Text, pa ->
11311             pr "%s x" pa
11312         | (field, pa) ->
11313             let fname = name_of_field field in
11314             pr "%s (child %S x)" pa fname
11315     ) (List.combine fields pas);
11316     pr "\n  ) in\n";
11317
11318     (match fields with
11319      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11320          pr "  t\n"
11321
11322      | _ ->
11323          pr "  (Obj.magic t : %s)\n" name
11324 (*
11325          List.iter (
11326            function
11327            | (Optional (Attribute (fname, [field])), pa) ->
11328                pr "  %s_%s =\n" name fname;
11329                pr "    %s x;\n" pa
11330            | (Optional (Element (fname, [field])), pa) ->
11331                pr "  %s_%s =\n" name fname;
11332                pr "    (let x = optional_child %S x in\n" fname;
11333                pr "     %s x);\n" pa
11334            | (field, pa) ->
11335                let fname = name_of_field field in
11336                pr "  %s_%s =\n" name fname;
11337                pr "    (let x = child %S x in\n" fname;
11338                pr "     %s x);\n" pa
11339          ) (List.combine fields pas);
11340          pr "}\n"
11341 *)
11342     );
11343     sprintf "parse_%s" name
11344   in
11345
11346   generate_parsers xs
11347
11348 (* Generate ocaml/guestfs_inspector.mli. *)
11349 let generate_ocaml_inspector_mli () =
11350   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11351
11352   pr "\
11353 (** This is an OCaml language binding to the external [virt-inspector]
11354     program.
11355
11356     For more information, please read the man page [virt-inspector(1)].
11357 *)
11358
11359 ";
11360
11361   generate_types grammar;
11362   pr "(** The nested information returned from the {!inspect} function. *)\n";
11363   pr "\n";
11364
11365   pr "\
11366 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11367 (** To inspect a libvirt domain called [name], pass a singleton
11368     list: [inspect [name]].  When using libvirt only, you may
11369     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11370
11371     To inspect a disk image or images, pass a list of the filenames
11372     of the disk images: [inspect filenames]
11373
11374     This function inspects the given guest or disk images and
11375     returns a list of operating system(s) found and a large amount
11376     of information about them.  In the vast majority of cases,
11377     a virtual machine only contains a single operating system.
11378
11379     If the optional [~xml] parameter is given, then this function
11380     skips running the external virt-inspector program and just
11381     parses the given XML directly (which is expected to be XML
11382     produced from a previous run of virt-inspector).  The list of
11383     names and connect URI are ignored in this case.
11384
11385     This function can throw a wide variety of exceptions, for example
11386     if the external virt-inspector program cannot be found, or if
11387     it doesn't generate valid XML.
11388 *)
11389 "
11390
11391 (* Generate ocaml/guestfs_inspector.ml. *)
11392 let generate_ocaml_inspector_ml () =
11393   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11394
11395   pr "open Unix\n";
11396   pr "\n";
11397
11398   generate_types grammar;
11399   pr "\n";
11400
11401   pr "\
11402 (* Misc functions which are used by the parser code below. *)
11403 let first_child = function
11404   | Xml.Element (_, _, c::_) -> c
11405   | Xml.Element (name, _, []) ->
11406       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11407   | Xml.PCData str ->
11408       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11409
11410 let string_child_or_empty = function
11411   | Xml.Element (_, _, [Xml.PCData s]) -> s
11412   | Xml.Element (_, _, []) -> \"\"
11413   | Xml.Element (x, _, _) ->
11414       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11415                 x ^ \" instead\")
11416   | Xml.PCData str ->
11417       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11418
11419 let optional_child name xml =
11420   let children = Xml.children xml in
11421   try
11422     Some (List.find (function
11423                      | Xml.Element (n, _, _) when n = name -> true
11424                      | _ -> false) children)
11425   with
11426     Not_found -> None
11427
11428 let child name xml =
11429   match optional_child name xml with
11430   | Some c -> c
11431   | None ->
11432       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11433
11434 let attribute name xml =
11435   try Xml.attrib xml name
11436   with Xml.No_attribute _ ->
11437     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11438
11439 ";
11440
11441   generate_parsers grammar;
11442   pr "\n";
11443
11444   pr "\
11445 (* Run external virt-inspector, then use parser to parse the XML. *)
11446 let inspect ?connect ?xml names =
11447   let xml =
11448     match xml with
11449     | None ->
11450         if names = [] then invalid_arg \"inspect: no names given\";
11451         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11452           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11453           names in
11454         let cmd = List.map Filename.quote cmd in
11455         let cmd = String.concat \" \" cmd in
11456         let chan = open_process_in cmd in
11457         let xml = Xml.parse_in chan in
11458         (match close_process_in chan with
11459          | WEXITED 0 -> ()
11460          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11461          | WSIGNALED i | WSTOPPED i ->
11462              failwith (\"external virt-inspector command died or stopped on sig \" ^
11463                        string_of_int i)
11464         );
11465         xml
11466     | Some doc ->
11467         Xml.parse_string doc in
11468   parse_operatingsystems xml
11469 "
11470
11471 (* This is used to generate the src/MAX_PROC_NR file which
11472  * contains the maximum procedure number, a surrogate for the
11473  * ABI version number.  See src/Makefile.am for the details.
11474  *)
11475 and generate_max_proc_nr () =
11476   let proc_nrs = List.map (
11477     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11478   ) daemon_functions in
11479
11480   let max_proc_nr = List.fold_left max 0 proc_nrs in
11481
11482   pr "%d\n" max_proc_nr
11483
11484 let output_to filename k =
11485   let filename_new = filename ^ ".new" in
11486   chan := open_out filename_new;
11487   k ();
11488   close_out !chan;
11489   chan := Pervasives.stdout;
11490
11491   (* Is the new file different from the current file? *)
11492   if Sys.file_exists filename && files_equal filename filename_new then
11493     unlink filename_new                 (* same, so skip it *)
11494   else (
11495     (* different, overwrite old one *)
11496     (try chmod filename 0o644 with Unix_error _ -> ());
11497     rename filename_new filename;
11498     chmod filename 0o444;
11499     printf "written %s\n%!" filename;
11500   )
11501
11502 let perror msg = function
11503   | Unix_error (err, _, _) ->
11504       eprintf "%s: %s\n" msg (error_message err)
11505   | exn ->
11506       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11507
11508 (* Main program. *)
11509 let () =
11510   let lock_fd =
11511     try openfile "HACKING" [O_RDWR] 0
11512     with
11513     | Unix_error (ENOENT, _, _) ->
11514         eprintf "\
11515 You are probably running this from the wrong directory.
11516 Run it from the top source directory using the command
11517   src/generator.ml
11518 ";
11519         exit 1
11520     | exn ->
11521         perror "open: HACKING" exn;
11522         exit 1 in
11523
11524   (* Acquire a lock so parallel builds won't try to run the generator
11525    * twice at the same time.  Subsequent builds will wait for the first
11526    * one to finish.  Note the lock is released implicitly when the
11527    * program exits.
11528    *)
11529   (try lockf lock_fd F_LOCK 1
11530    with exn ->
11531      perror "lock: HACKING" exn;
11532      exit 1);
11533
11534   check_functions ();
11535
11536   output_to "src/guestfs_protocol.x" generate_xdr;
11537   output_to "src/guestfs-structs.h" generate_structs_h;
11538   output_to "src/guestfs-actions.h" generate_actions_h;
11539   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11540   output_to "src/guestfs-actions.c" generate_client_actions;
11541   output_to "src/guestfs-bindtests.c" generate_bindtests;
11542   output_to "src/guestfs-structs.pod" generate_structs_pod;
11543   output_to "src/guestfs-actions.pod" generate_actions_pod;
11544   output_to "src/guestfs-availability.pod" generate_availability_pod;
11545   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11546   output_to "src/libguestfs.syms" generate_linker_script;
11547   output_to "daemon/actions.h" generate_daemon_actions_h;
11548   output_to "daemon/stubs.c" generate_daemon_actions;
11549   output_to "daemon/names.c" generate_daemon_names;
11550   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11551   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11552   output_to "capitests/tests.c" generate_tests;
11553   output_to "fish/cmds.c" generate_fish_cmds;
11554   output_to "fish/completion.c" generate_fish_completion;
11555   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11556   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11557   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11558   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11559   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11560   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11561   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11562   output_to "perl/Guestfs.xs" generate_perl_xs;
11563   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11564   output_to "perl/bindtests.pl" generate_perl_bindtests;
11565   output_to "python/guestfs-py.c" generate_python_c;
11566   output_to "python/guestfs.py" generate_python_py;
11567   output_to "python/bindtests.py" generate_python_bindtests;
11568   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11569   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11570   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11571
11572   List.iter (
11573     fun (typ, jtyp) ->
11574       let cols = cols_of_struct typ in
11575       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11576       output_to filename (generate_java_struct jtyp cols);
11577   ) java_structs;
11578
11579   output_to "java/Makefile.inc" generate_java_makefile_inc;
11580   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11581   output_to "java/Bindtests.java" generate_java_bindtests;
11582   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11583   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11584   output_to "csharp/Libguestfs.cs" generate_csharp;
11585
11586   (* Always generate this file last, and unconditionally.  It's used
11587    * by the Makefile to know when we must re-run the generator.
11588    *)
11589   let chan = open_out "src/stamp-generator" in
11590   fprintf chan "1\n";
11591   close_out chan;
11592
11593   printf "generated %d lines of code\n" !lines